C++ 核心特性详解
目录
- 6. 引用
- 概念和定义
- 小试牛刀
- 引用的作用
- const引用
- 引用和指针的关系
- 7. 宏函数
- 8. inline 内联函数
- 9. nullptr
6.引用
这是C++入门部分最大的一个重点,也是改进 C语言最大的一个特点
概念和定义
引用不是新定义一个变量,而是给已经存在的变量取别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共同用一块内存空间
类型& 引用别名 = 引用对象
引用的特性:
• 引用在定义时必须初始化
• 一个变量可以有多个引用
• 引用一旦引用一个实体,再不能引用其他实体
小试牛刀
cout 自动识别类型,&a是取地址,int*类型,按照地址打印,&b是引用,运行结果显示出二者的地址是相同的,这也反向印证了引用没有开辟新空间,就是给变量取别名在这里让b++,我们同时打印,发现a和b同时加了1那一个变量能否取多个别名呢,是可以的,下面我们看到不管添加多少变量,打印出来的地址都是相同的
引用是不会改变指向的,这里c是a的别名,那就一直都是a的别名,不会把x赋值给c,所以这里是把x赋值修改c
引用的作用
引⽤和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引⽤跟其他语⾔的引⽤(如Java)是有很⼤的区别的,除了⽤法,最⼤的点,C++引用定义后不能改变指向,Java的引用可以改变指向。
引用功能1:做函数形参,修改形参影响实参
引用功能2:做函数形参,减少拷贝,提高效率
引用功能3:引用做返回值类型,修改返回对象
引用功能4:引用做返回值类型,减少拷贝,提高效率不用传地址,直接引用实参,修改形参的同时实参也改变;直接引用结构体,就不再申请空间拷贝结构体①返回ret时,函数内存已经销毁②xxx会非法访问原来已经释放的空间,导致x值的变化
引用不能改变指向,所以在链式结构中,无法替代指针,这些场景必须使用指针Java中只有引用,没有指针,这里的引用可以改变指向
const引用
•①可以引⽤⼀个const对象,但是必须⽤const引⽤。const引⽤也可以引⽤普通对象,因为对象的访问权限在引⽤过程中可以缩⼩,但是不能放⼤。
②不需要注意的是类似 int& rb = a3; double d = 12.34; int& rd = d; 这样⼀些场景下a3的和结果保存在⼀个临时对象中, int& rd = d 也是类似,在类型转换中会产⽣临时对象存储中间值,也就是时,rb和rd引⽤的都是临时对象,⽽C++规定临时对象具有常性,所以这⾥就触发了权限放⼤,必须要⽤常引⽤才可以。
③所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象,C++中把这个未命名对象叫做临时对象。权限不能放大,权限可以缩小指针和引用才涉及到权限的放大和缩小
引用和指针的关系
C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有自己的特点,互相不可替代。- 语法概念上引用是一个变量的取别名
不开空间,指针是存储一个变量地址,要开空间。
- 引用在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
- 引用在初始化时引用一个对象后,就不能再引用其他对象;而指针可以在不断地改变指向对象。
- 引用可以直接访问指向对象,指针需要解引用才是访问指向对象。
- sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte)
- 指针很容易出现空指针和野指针的问题,引用很少出现,引用使用起来相对更安全一些。
7.宏函数
宏是一种替换
缺点:复杂 / 类型安全检查 / 不能调试
优点:预处理阶段战替换,不用建立栈帧,本质是一种提效
8.inline 内联函数
1.⽤inline修饰的函数叫做内联函数,编译时C++编译器会在调⽤的地⽅展开内联函数,这样调⽤内联函数就需要建⽴栈帧了,就可以提⾼效率。
2.inline对于编译器⽽⾔只是⼀个建议,也就是说,你加了inline编译器也可以选择在调⽤的地⽅不展开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个。inline适⽤于频繁调⽤的短小函数,对于递归函数,代码相对多⼀些的函数,加上inline也会被编译器忽略。
3.C语⾔实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不⽅便调试,C++设计了inline⽬的就是替代C的宏函数。
4.vs编译器 debug版本下⾯默认是不展开inline的,这样⽅便调试,debug版本想展开需要设置⼀下以下两个地⽅。5.inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。
9.nullptr
NULL实际是⼀个宏,在传统的C头⽂件(stddef.h)中,可以看到如下代码:
#ifndefNULL#ifdef__cplusplus#defineNULL0#else#defineNULL((void*)0)#endif#endif1.C++中NULL可能被定义为字⾯常量0,或者C中被定义为⽆类型指针(void*)的常量。不论采取何种定义,在使⽤空值的指针时,都不可避免的会遇到⼀些⿇烦,本想通过f(NULL)调⽤指针版本的f(int*)函数,但是由于NULL被定义成0,调⽤了f(int x),因此与程序的初衷相悖。f((void*)NULL);调⽤会报错。
2.C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,⽽不能被转换为整数类型。