深入学习C++——17引用
引用是一种引用现有变量的方式。与指针不同,指针可以创建空指针,而引用不行。引用必须引用已存在的变量。引用本身不是一个新变量,它不占用内存,没有自己的存储空间。
我们创建一个变量,并给这个变量创建一个引用。声明引用时需要指定变量类型:
int a = 5;
int& ref = a;
这里的ref就是a的别名,它本身不是一个真正的变量,ref变量实际并不存在,它只存在于代码中。
此时我们可以给ref赋值,然后输出a的值:
ref = 2;
std::cout << a << std::endl;
运行程序,可以看到a的值变成了2。
下面来看一个更复杂的例子。我们创建一个变量递增函数,并在main中调用,把a作为参数传递进去,只是通过值传递给它。
void Increment(int value)
{
value++;
}
int main()
{
int a = 5;
Increment(a);
std::cout << a << std::endl;
}
运行程序,可以看到a的值仍为5,并没有递增。实际上a传入Increment函数后创建了一个全新的变量value且等于a的值,其作用大致等效于:
void Increment(int value)
{
int value = 5;
value++;
}
前面我们讲了指针,自然而然可以想到:我们并不直接把a的值传进函数,而是将a的内存地址传进去,然后在函数内寻找这个内存地址上的数据并对其进行操作即可。所以程序修改为:
void Increment(int* value)//传入一个指针
{
//value++;//错误。这样只会递增value指针的地址,只是把一个指针递增了而已
//*value++;//错误。这样写操作顺序为先递增内存地址再逆向引用
(*value)++;//先逆向引用,再将值自增
}
int main()
{
int a = 5;
Increment(&a);//传入变量的内存地址
std::cout << a << std::endl;
}
此时运行程序可以看到a的值被成功修改成了6。
有没有觉得使用指针的时候*
和&
满天乱飞,本文讲了引用,那我们就通过另一种更为简洁的方法实现以上功能:我们可以用引用代替指针:
void Increment(int& value)//传入一个引用
{
value++;//这里也不需要逆向引用*了
}
int main()
{
int a = 5;
Increment(a);//只需传递a即可
std::cout << a << std::endl;
}
运行程序,a成功地被修改成了6。
综上,指针比引用更强大,能用引用的地方也一定能用指针,但是能用引用就用引用,这样会使程序更为简洁和干净。
不过要注意,声明引用的时候也必须给引用赋值,因为它并不是一个真正的变量,不能为空。并且一旦声明了一个引用,不能改变它引用的东西。
int a = 5;
int b = 8;
int& ref = a;
ref = b;
// now a = 8, b = 8
这段程序只是将b的值赋给了a,并没有改变ref引用的东西。如果想要实现这个功能只能使用指针:
int a = 5;
int b = 8;
int* ref = &a;
*ref = 2;
ref = &b;
*ref = 1;
// now a = 2, b = 1