C++语法基础(下)

(注:在看本文是如果感觉内容有点突兀,请先浏览《C++语法基础(上)》这篇文章帮助更好理解)

一.缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
 
• 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++ 规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。

示例代码:
 以上代码,展示了全缺省参数和半缺省参数的函数定义与使用。 add 函数是全缺省参数示例, sub 函数为半缺省参数示例。通过在 main 函数中调用,呈现不传参时使用缺省值,传参时使用指定实参的效果。


• 带缺省参数的函数调用,C++ 规定必须从左到右依次给实参,不能跳跃给实参。
 
• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。

 

二.引用

1.引用的概念与定义

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:《水浒传》中李逵,宋江叫“铁牛”,江湖上人称“黑旋风”;林冲,外号豹子头。所以一个引用也可以有多个别名。

类型& 引用别名 = 引用对象;

以上C++ 代码,在 main 函数中,先定义了变量 a 并赋值为2 。接着定义了 b 和 c 作为 a 的引用,由于引用与被引用变量共用内存空间,对 c 执行自增操作后, a 、 b 、 c 的值都变为3 ,运行结果验证C++ 中引用的这一特性。

2.引用的特性

引用在定义时必须初始化
②一个变量可以有多个引用
③引用一旦引用一个实体,再不能引用其他实体

 3.引用的使用

在C++ 实践中,引用主要发挥于引用传参与引用返回值两大场景:

- 引用传参:与指针传参功能近似,却更具便捷性。通过引用传递参数,可规避对象拷贝,提升程序运行效率,且能直接操作实参,改变其值。

- 引用返回值:应用场景较为复杂,这里先作简要介绍,后续在类和对象章节将深入探讨。它同样能减少拷贝开销,有时还可用于实现对特定对象的持续引用操作 。

 引用与指针在实际运用中相互配合,虽功能有所重叠,但各自特性鲜明,无法相互取代。值得注意的是,C++ 的引用与Java 等语言的引用差异显著。C++ 中引用一经定义,便无法更改指向;而Java 里的引用则无此限制,可灵活变更指向。

 部分以C 代码为主的《数据结构》教材,会采用C++ 引用替换指针传参,旨在简化程序逻辑,规避指针操作的复杂性。

引用传参和指针传参

 以上C++ 代码展示了两种实现交换功能的函数:一个通过引用传参( Swap(int& x, int& y)  ),另一个通过指针传参( Swap(int* x, int* y)  ) 。在 test 函数中对这两个函数进行调用测试,分别传入变量和变量地址。运行结果表明,二者都能成功实现变量值的交换,直观体现引用和指针在参数传递用于修改实参值时的作用。

4.const引用

在C++ 里, const 引用即常量引用 ,它是对变量的只读引用(但不能赋值)。
 
从定义来讲,当用 const 修饰引用时,就创建了这种只读关系,一旦绑定到某个对象,通过该引用不能修改所绑定对象的值 。比如 const int& ret = a;  ,此后不能执行 ret = 新值;  这样的操作 。
 
其主要作用体现在两方面:
 ①避免数据拷贝:在函数参数传递中,若传递大对象,按值传递会产生拷贝开销,使用 const 引用传递,能避免拷贝,提升程序性能 。例如函数 void func(const 大对象类型& obj)  ,调用时不会对实参进行拷贝 。

②保证数据不可变性:能确保在函数内部不会意外修改引用的数据,为数据安全性提供保障 。在多函数调用、多人协作开发等场景下,可防止数据被误改,让代码逻辑更清晰、可靠 。
 
此外, const 引用还有个特殊之处,它可以和声明类型不匹配 ,比如 const int& r = 3.14;  (编译器会创建临时量来实现转换和绑定 ),但普通引用不允许这样做 。

以下示例:

 代码展示了 const 引用的特性。在 main 函数中,定义变量 a 并赋值为2 ,接着创建 const int& ra  作为 a 的常量引用。由于 ra 是 const 引用,不能对其执行自增操作(如 ra++  被注释掉 ),但原变量 a 可以自增。运行结果显示 a 自增后的值为3 , ra 的值也同步变为3 ,体现 const 引用只读且与原变量关联的特性。

 这段 代码在 main 函数中,先定义了常量 a 和变量 b  ,然后分别创建了它们的 const 引用 ra 和 rb  。代码注释指出, int& ra = a;  这种写法是错误的 。因为 a 是 const 类型,普通引用不能绑定到 const 对象上,而 const 引用能确保不会通过引用意外修改对象的值,此例直观体现const 引用的使用规则和对象绑定限制。

 这段 代码在 main 函数中,展示了 const 引用的特殊用法及普通引用的限制。定义变量 a 后, const int& ra = 30;  直接绑定字面量,体现 const 引用可绑定临时值。而 int& rb = a * 3;  等普通引用绑定临时值或类型不匹配值会编译报错。 const int& rb = a * 3;  、 const int& rd = d;  能成功,表明 const 引用可在类型转换等情况下,通过创建临时变量实现绑定,凸显 const 引用与普通引用在对象绑定上的差异。

 

5.引用与指针对比

(1 )定义与初始化
 
- 指针:指针是一个变量,存储的是另一个变量的内存地址。它可以先定义,之后再赋值。例如  int *ptr;  先定义了一个整型指针  ptr ,后续可以  ptr = #  让它指向变量  num 。指针初始化不是必须的,但未初始化就使用会导致未定义行为。
 
- 引用:引用是已存在变量的别名,必须在定义时初始化。例如  int num; int &ref = num;  定义  ref  作为  num  的引用,此后  ref  一直关联  num ,无法再引用其他变量。
 
(2)内存占用
 
- 指针:指针本身需要占用内存空间来存储所指向变量的地址。在32位系统中,指针通常占用4字节;64位系统中,指针一般占用8字节。
 
- 引用:从概念上讲,引用不占用额外内存空间,因为它只是原变量的别名。但在实际实现中,某些编译器可能会为引用分配与指针相同大小的空间来实现引用的功能。
 
(3)使用方式
 
- 指针:使用指针访问其所指向变量的值时,需使用解引用操作符  * 。例如  int num = 10; int *ptr = # int value = *ptr; ,这里通过  *ptr  获得  ptr  所指向的  num  的值。指针还支持指针运算,如  ptr++  可移动指针指向同一类型数组的下一个元素。
 
- 引用:使用引用就像使用原变量本身,直接通过引用名访问和操作关联变量。例如  int num = 10; int &ref = num; int value = ref; ,直接使用  ref  即可,无需额外操作符。
 
(4)空值情况
 
- 指针:指针可以指向空值,即  nullptr (C++11 引入,之前用  NULL )。例如  int *ptr = nullptr; ,在使用指针前通常需要检查其是否为空,以避免空指针解引用错误。
 
- 引用:引用不能指向空值,因为定义引用时必须初始化,且一旦初始化就不能再改变引用对象。
 
(5)可修改性
 
- 指针:指针本身的值(即所指向的地址)可以改变,使其指向不同的变量。例如  int num1 = 10, num2 = 20; int *ptr = &num1; ptr = &num2; ,指针  ptr  先指向  num1 ,之后可重新指向  num2 。
 
- 引用:引用一旦初始化,就不能再引用其他变量,始终与初始化时的变量绑定。
 
(6)应用场景
 
- 指针:常用于动态内存分配与释放,操作数组,实现数据结构(如链表、树)等场景。指针的灵活性使其在复杂数据操作中发挥重要作用。
 
- 引用:主要用于函数参数传递和返回值,避免对象拷贝开销,同时保证对原对象的直接操作。在运算符重载等场景也常使用引用,以提供自然的语法和高效的操作。

 

三.nullptr

在C++ 中, 引入nullptr  是为了替代NULL ,虽然两者都可以 用于表示指针为空的状态,但两者存在差异。

 从类型角度, NULL  本质是整数  0  或预处理器宏定义为  0 ,常被视为整型,虽可赋值给指针,但会造成类型不匹配隐患。而  nullptr  是C++11引入的关键字,类型为  std::nullptr_t ,专门用于表示空指针,与任何指针类型都能隐式转换,类型安全性更好。

 使用场景上, NULL  在C和早期C++代码中广泛使用,不过在C++ 中易导致函数重载歧义,因它可被当成整数参与重载决议。 nullptr  则消除了这种歧义,在C++11及以后代码中,推荐使用  nullptr  表示空指针,使代码更清晰、安全,符合现代C++ 类型系统规范。

 这段C++ 代码定义了两个重载函数 f(int x)  和 f(int* ptr)  。在 main 函数中进行调用测试, f(0)  调用了 f(int x)  。原本想通过 f(NULL)  调用指针版本的函数,却因 NULL  被定义为0 ,实际调用了 f(int x)  。 f((int*)NULL)  能正确调用指针版本,而 f((void*)NULL)  编译报错。使用 nullptr  则可准确调用 f(int* ptr)  ,清晰展现函数重载下指针类型调用及 NULL  与 nullptr  的区别。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣Hot100(Java版本)

1. 哈希 1.1 两数之和 题目描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同…

FCB文件疑问+求助:01 百度网盘视频自动生成AI笔记pdf会出现对应fcb文件-作用待详解

疑问求助:01 百度网盘视频自动生成AI笔记pdf会出现对应fcb文件-作用待确认确认详解.md 一、疑惑起因 百度网盘视频自动生成AI笔记pdf会出现对应fcb文件,我可以删除fcb文件么?影响什么?如何打开fcb其内容是啥?直观看删…

【数据结构】——栈和队列OJ

一、有效的括号 题目链接: 20. 有效的括号 - 力扣(LeetCode) 题目的要求很简单,就是要求我们判断其输入的括号字符串是否是有效的括号,那么我们要如何判断呢? 我们可以这样,我们遍历出传入的…

开源免费无广告专注PDF编辑、修复和管理工具 办公学术 救星工具

各位PDF处理小能手们!我跟你们说啊,今天要给大家介绍一款超牛的国产开源PDF处理工具,叫PDFPatcher,也叫PDF补丁丁。它就像一个PDF文档的超级修理工,专门解决PDF编辑、修复和管理的各种难题。 这软件的核心功能和特点&a…

【Bluedroid】蓝牙 HID DEVICE 初始化流程源码解析

本文深入剖析Android蓝牙协议栈中HID设备(BT-HD)服务的初始化与启用流程,从接口初始化、服务掩码管理、服务请求路由到属性回调通知,完整展现蓝牙HID服务激活的技术路径。通过代码逻辑梳理,揭示服务启用的核心机制&…

2025年项目管理软件革命:中国技术主权与全球创新浪潮的交锋

全球项目管理软件市场正在经历一场由多重技术叠加引发的结构性变革。根据Gartner最新预测,到2025年项目管理工具市场规模将突破220亿美元,其中中国市场增速达38%,远超全球平均水平。这场变革不仅关乎工具功能迭代,更深刻影响着企业…

计算机组成与体系结构:组相联映射(Set-Associative Mapping)

目录 🧩 映射方式问题回顾 🏗️ 组相联映射 工作流程 地址结构 ♻️ 替换策略 示例: 优点 ⚖️ 与其他映射方式对比 🧩 映射方式问题回顾 直接映射的问题: 优点:实现简单,查找速度快…

机器学习第八讲:向量/矩阵 → 数据表格的数学表达,如Excel表格转数字阵列

机器学习第八讲:向量/矩阵 → 数据表格的数学表达,如Excel表格转数字阵列 资料取自《零基础学机器学习》。 查看总目录:学习大纲 关于DeepSeek本地部署指南可以看下我之前写的文章:DeepSeek R1本地与线上满血版部署:…

基于Spring AI实现多轮对话系统架构设计

文章目录 基于Spring AI实现多轮对话系统架构设计 前言 一、多轮对话系统核心架构 1.1 架构概览 1.2 Spring AI核心优势 二、ChatClient与多轮对话设计 2.1 ChatClient的特性与角色 2.2 实现多轮对话方法 三、Advisors拦截器机制 3.1 Advisors概念与工作原理 3.2 对…

C++中的虚表和虚表指针的原理和示例

一、基本概念 1. 什么是虚函数(virtual function)? 虚函数是用 virtual 关键字修饰的成员函数,支持运行时多态(dynamic polymorphism)。通过基类指针或引用调用派生类重写的函数。 class Base { public:…

FPGA:XILINX FPGA产品线以及器件选型建议

本文将详细介绍Xilinx(现为AMD的一部分)当前的FPGA产品线及其主要特点,并提供器件选型的建议。以下内容基于Xilinx FPGA的最新信息,涵盖产品系列、特性及选型指导。由于Xilinx已被AMD收购,产品线以AMD Xilinx品牌为主&…

【C++】多线程和多进程

在C++中,多线程通信(同一进程内的线程间交互)和进程间通信(IPC,不同进程间的数据交换)是构建并发系统的核心技术。以下是两种通信机制的详细介绍和典型实现: 一、多线程通信(线程间同步与数据共享) 1. 共享内存与同步原语 通过全局变量或对象成员变量实现数据共享,…

PC Cleaner软件,它能帮助用户轻松清理和优化电脑,提升系统性能。

不用破解就能用!这款超神的电脑清理 Pro 版,绝了! 宝子们,我是你们的数码小助手蓝木云!不知道大家有没有这种感觉,电脑用久了,就像住久了没打扫的屋子,越来越 “乱”,运…

linux中fork()函数的小问题

问题描述&#xff1a;分析下列代码&#xff0c;分别能产生多少a // 1 for(int i0; i<3; i){ printf("a\n"); fork(); }// 2 for(int i0; i<3; i){ fork(); printf("a\n"); }// 3 for(int i0; i<3; i){ fork(); printf("a"); } fflus…

阿克曼-幻宇机器人系列教程2- 机器人交互实践(Topic)

在上一篇文章中&#xff0c;我们介绍了两种登录机器人的方式&#xff0c;接下来我们介绍登录机器人之后&#xff0c;我们如何通过topic操作命令实现与机器人的交互。 1. 启动 & 获取topic 在一个终端登录树莓派后&#xff0c;执行下列命令运行机器人 roslaunch huanyu_r…

51c嵌入式~电路~合集27

我自己的原文哦~ 一、7805应用电路 简介 如上图&#xff0c;7805 集成稳压电路。 7805是串联式三端稳压器&#xff0c;三个端口分别是电压输入端&#xff08;IN&#xff09;&#xff0c;地线&#xff08;GND&#xff09;&#xff0c;稳压输出&#xff08;OUT&#xff09;…

Vitrualbox完美显示系统界面(只需三步)

目录 1.使用vitrualbox的增强功能&#xff1a;​编辑 2.安装增强功能&#xff08;安装完后要重启虚拟机&#xff09;&#xff1a; 3. 调整界面尺寸&#xff08;如果一个选项不行的话&#xff0c;就多试试其他不同的百分比&#xff09;&#xff1a; 先看看原来的&#xff0c;…

2025年第十六届蓝桥杯软件赛省赛C/C++大学A组个人解题

文章目录 题目A题目C&#xff1a;抽奖题目D&#xff1a;红黑树题目E&#xff1a;黑客题目F&#xff1a;好串的数目 https://www.dotcpp.com/oj/train/1166/ 题目A 找到第2025个素数 #include <iostream> #include <vector> using namespace std; vector<i…

电机控制储备知识学习(一) 电机驱动的本质分析以及与磁相关的使用场景

目录 电机控制储备知识学习&#xff08;一&#xff09;一、电机驱动的本质分析以及与磁相关的使用场景1&#xff09;电机为什么能够旋转2&#xff09;电磁原理的学习重要性 二、电磁学理论知识1&#xff09;磁场基础知识2&#xff09;反电动势的公式推导 附学习参考网址欢迎大家…

JMeter同步定时器 模拟多用户并发访问场景

同步定时器 JMter同步定时器的作用主要在于模拟多用户并发访问的场景&#xff0c;确保多个线程能够同时执行某个操作&#xff0c;达到真正的并发效果。 当多个线程同时启动时&#xff0c;它们可能会在不同的时间间隔内执行&#xff0c;这样就无法达到真正的并发效果。&#xff…