引用的补充(接上回)
引用做返回值
- 作用:引用是可以作为函数的返回值存在的
- 注意:不要返回局部变量
- 用法:函数调用作为左值
- 为什么不要返回局部变量引用?接如下代码:
#include<iostream> using namespace std; int& test() { int a = 20; return a; } int main() { int& ret = test(); cout << "a is: " << ret << endl; cout << "a is: " << ret << endl; return 0; }
👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇
运行结果为: --由上代码可见第一次打印的是a=20与预期的一样,但第二次就打印出一个2076150152,原因是局部变量a被存在四区中的栈区上,当调用完test函数后a就会被释放掉。第一次能打印出来是因为编译器对此有所保留,所以在打印第二次的时候就打印错误。
- 函数调用作为左值;如下代码:
#include<iostream> using namespace std; int& test() { static int a = 10; return a; } int main() { int& ret = test(); cout << "a is: " << ret << endl; cout << "a is: " << ret << endl; test() = 40; cout << "a is: " << ret << endl; cout << "a is: " << ret << endl; return 0; }
👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇
运行结果为: --由上代码见,因为test函数里的a用static修饰储存在四区中的静态区,静态区是当程序结束时才销毁所以上面两条cout打印出来的是10,函数调用也可以作为等号左值进行赋值使用 实现代码为test() = 40;
Const 引用
访问权限可以缩小但不能放大
- 可以引用⼀个const对象,但是必须⽤const引用。const引用也可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大。由下代码实现: --这样就是实现了对象的访问权限被缩小,我们不能通过a的别名ra来修改a的值从而实现访问权限缩小;
- 权限不能放大由下代码实现: 这串代码就验证了对象的访问权限不能被放大,因为int a是被const修饰的 属于常量,如果说我们的int& ra = a不报错的话那就意味着我们可以通过ra 来修改a的值,但这里报错了这也恰恰证明了对象的访问权限不能被放大。
临时对象具有常性
- 在不同的类型进行转换或者实现int a = 10;引用a*10时会产生一个临时对象储存中间值,而C++规定临时对象具有常性,要想对临时对象进行引用则需要加const如果不加则会报错,实现代码如下:
#include<iostream> using namespace std; int main() { int a = 10; const int& ra = 10 * 3; cout << "ra is: " << ra << endl; double b = 13.14; const int& rb = b; cout << "rb is: " << rb << endl; return 0; }
👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇
运行结果为:
对上的补充:所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象,C++中把这个未命名对象叫做临时对象。
inline的介绍以及使用
- 同C语言的宏函数一样在预处理时也会被展开,但宏函数实现时有很多地方要注意的而且还不方便调试所以C++的inline是为了替代C的宏函数;实现如下代码:
#include<iostream> using namespace std; //1. 为什么要加外边层括号,因为如果不加 //想要实现ADD(a,b)*5的时候被预处理后会变成a+b*5; //2. 为什么要加里边层括号 //想要实现ADD(x & y, x | y)的时候被预处理后会变成(x&y+x|y) //而+号的优先级大于&和| //正确的实现宏函数的方式 #define ADD(a,b)((a)+(b)) inline int add(int a, int b) { return a + b; } int main() { int ra1 = ADD(1, 2); int ra2 = add(1, 2); cout << "ra1 is: " << ra1 << endl; cout << "ra2 is: " << ra2 << endl; return 0; }
👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇
运行结果为:
-
inline不建议声明和定义分离到两个文件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。
-
inline适用于频繁调用的短小函数,对于递归函数和代码量较大的函数加上inline也会被编译器忽略掉。
nullptr
- 在C++中NULL可能被定义为常量0,所以C++引用了nullptr;如下代码所示:
#include<iostream> using namespace std; void test(int x) { cout << "test(int x)的调用" << endl; } void test(int* p) { cout << "test(int* p)的调用" << endl; } int main() { test(1); test(NULL); return 0; }
👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇 👇
运行结果为:
-
C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换成任意其他类型的指针类型。使用nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,而不能被转换为整数类型。
C++入门知识End!
- 在C++中NULL可能被定义为常量0,所以C++引用了nullptr;如下代码所示: