目录
一、引用
1.引用的概念
引用可以看成某个变量的别名。
#include <iostream>
using namespace std;
int main()
{
int x = 1;
int& y = x;
cout << x << endl;
cout << y << endl;
//引用改变,变量也跟着改变
y = 2;
cout << x << endl;
cout << y << endl;
return 0;
}
2.引用的一些细节
引用的地址和变量的地址一致
引用必须定义的时候初始化
一个变量可以有多个引用
引用一旦引用一个变量后就不能引用其他变量
#include <iostream>
using namespace std;
int main()
{
int x = 1;
int& y = x;
cout << &x << endl;
cout << &y << endl;
return 0;
}
3.常引用
权限可以不变,可以缩小,不可以放大。
//权限不变
int x = 0;
int& y = x;
//权限缩小
int x = 0;
const int& y = x;//常引用
//权限放大
const int x = 0;
int& y = x;
4.引用作为函数参数
#include <iostream>
using namespace std;
void Swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int x = 10;
int y = 20;
Swap(x, y);
cout << "x = " << x << endl;
cout << "y = " << y << endl;
return 0;
}
5.引用作为函数返回值
只有当变量所控制的空间出了作用域还没有被释放,才可以使用传引用返回。
#include <iostream>
using namespace std;
int& Add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int& sum = Add(1, 2);
Add(10, 20);
cout << "1 + 2 = " << sum << endl;
//可以看到sum是z的引用,但z出了作用域后就被释放了
//这时候如果输出sum,sum的值是不能确定的
//也就是说这段程序是错误的!
return 0;
}
6.引用作为函数参数时的效率
结构体传参时,要用结构体的指针作为函数参数。如果用结构体作为函数参数,当结构体很大时,参数压栈会有比较大的开销,使效率降低。这里我们来比较结构体和结构体引用哪个效率更优:
#include <iostream>
#include <time.h>
using namespace std;
struct A
{
int data[2000];
int size;
};
//使用结构体作为函数参数
void F1(struct A a)
{
a.size = 0;
}
//使用结构体引用作为函数参数
void F2(struct A& a)
{
a.size = 0;
}
int main()
{
struct A a = { {0}, 0 };
int64_t i = 0;
int64_t start1 = clock();
for (i = 0; i < 100000000; ++i)
{
F1(a);
}
int64_t end1 = clock();
int64_t start2 = clock();
for (i = 0; i < 100000000; ++i)
{
F2(a);
}
int64_t end2 = clock();
cout << end1 - start1 << endl;
cout << end2 - start2 << endl;
return 0;
}
我的环境是vs2022,cpu是i5-10210U,每秒可以执行...嗯...很多很多条机器指令( o(* ̄▽ ̄*)o),在Release版本下,程序运行结果是:使用结构体作为函数参数需要花费120ms左右的时间,而使用结构体引用作为函数参数需要花费不到0ms的时间,所以使用引用效率更好。
7.引用作为函数返回值时的效率
#include <iostream>
#include <time.h>
using namespace std;
struct A
{
int data[2000];
int size;
};
//使用结构体作为函数返回值
struct A F1(struct A a)
{
a.size = 0;
return a;
}
//使用结构体引用作为函数返回值
struct A& F2(struct A a)
{
a.size = 0;
return a;
}
int main()
{
struct A a = { {0}, 0 };
int64_t i = 0;
int64_t start1 = clock();
for (i = 0; i < 1000000; ++i)
{
F1(a);
}
int64_t end1 = clock();
int64_t start2 = clock();
for (i = 0; i < 1000000; ++i)
{
F2(a);
}
int64_t end2 = clock();
cout << end1 - start1 << endl;
cout << end2 - start2 << endl;
return 0;
}
Release版本下,使用结构体作为函数返回值需要花费190ms左右的时间,使用结构体引用作为函数返回值需要花费120ms左右的时间,故使用引用返回效率更好。
细心的朋友可能发现了函数F1、F2中都有一句不痛不痒的a.size = 0,这是为了对抗编译器的优化。实际上,现在的编译器都非常聪明,如果不写a.size = 0,当调用函数的时候,编译器发现这个函数啥也没干,直接就给优化掉了,还想调用?不存在的,结果就是,无论循环多少遍,运行时间都是0。而平时我们肯定不会写这么无聊的函数,所以如果可以的话,使用引用作为函数的返回值是很有意义的!
8.引用与指针的区别
引用的底层是用指针实现的
int x = 0;
int& rx = x;
rx = 1;
int* px = &x;
*px = 1;
我们对这段代码进行反汇编:
可以看到,引用和指针的汇编语言是一样的,但它们俩还是有一定区别的:
引用在定义的时候必须初始化,指针不用。
无空引用,有空指针。
无多级引用,有多级指针。
引用在引用一个变量后,不能改变,指针在指向一个变量后,可以改变。
sizeof(引用)的结果由所引用的变量类型决定,sizeof(指针)的结果由机器字长(常见的有32位和64位)决定。
二、内联函数
1.内联函数的使用
//使用inline修饰的函数就是内联函数
inline int Add(int x, int y)
{
return x + y;
}
int main()
{
Add(1, 2);
return 0;
}
2.内联函数的一些细节
内联函数只是我们向编译器发送的一个请求,编译器可以忽略这个请求。如果编译器同意了这个请求,则会在编译阶段把函数调用替换成函数体,如此一来就省去了函数调用的开销,提高了程序的运行效率,但可能会使编译后的可执行文件体积变大。
对于逻辑简单,代码量小,频繁调用,且没有递归的函数可以考虑使用内联函数。
内联函数的声明和定义不能分离,否则会导致链接错误。
三、auto
1.auto的使用
C++11中,auto定义的变量由编译器在编译时自动推导出其类型,且auto定义的变量必须初始化
//i的类型为int,c的类型为char
auto i = 0;
auto c = '!';
2.auto的一些细节
auto不能定义函数参数
auto不能定义数组
auto对指针与引用的识别
#include <iostream>
using namespace std;
int main()
{
//y和z的类型都是int*
int x = 0;
auto y = &x;
auto* z = &x;
cout << y << endl;
cout << z << endl;
//要想识别为引用,必须带&
int a = 0;
auto& b = a;
cout << &a << endl;
cout << &b << endl;
return 0;
}
四、范围for
范围for的使用
#include <iostream>
using namespace std;
int main()
{
int arr[100] = { 0 };
for (auto& i : arr)
{
i = 1;
}
for (auto i : arr)
{
cout << i;
}
cout << endl;
return 0;
}
五、nullptr
nullptr的由来
既然都有NULL了,为什么还会有nullptr呢?在C语言的stddef.h中我们可以看到对NULL的解释(NULL - cppreference.com):
可以看到,在C++中,NULL可能会被宏定义为值为0的整数常量表达式,而我们期望NULL代表的意思是指针空值(void*)0,所以C++11起引入关键字nullptr,并规定关键字nullptr代表指针空值!
C++官方文档对nullptr的解释(nullptr ,指针字面量 - cppreference.com):
C++官方文档网址:cppreference.com
最后,分享一张好看的图片(´・ ᴗ ・`)