引用变量是一个别名,它是某个已存在的变量的另外一个名字。编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
一旦把引用初始化为某个变量,就可以使用引用名称(别名)来指向变量。(它们在内存空间的地址完全一样)
引用的格式:
类型 & 引用变量名(对象名) = 引用实体;
示例:
#include <stdio.h>
int main()
{
int a = 100;
int &b = a;
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("address a = %p\n", &a);
printf("address b = %p\n", &b);
return 0;
}
结果输出:
a = 100
b = 100
address a = 0x7ffec98e696c
address b = 0x7ffec98e696c
1. C++引用相关的重要概念
- 把引用作为参数:C++支持把引用作为参数传递给函数,这比一般的函数传参更安全;
- 把引用作为返回值:可以从 C++函数中返回引用,就像返回其他数据类型一样。注意:不要返回局部变量的引用
首先,是引用作为参数的案例:
把传值和传址的优点结合起来了,写起来会比较方便,同时对形参的修改会体现到我们的外部实参上(因为形参就是实参的别名),同时传引用的效率比传值的效率高,传引用写起来也比传址方便。
#include <stdio.h>
void swap(int &a, int &b)
{
a ^= b;
b ^= a;
a ^= b;
}
int main()
{
int a = 100;
int b= 10;
printf("a = %d, b = %d\n", a, b);
swap(a, b);
printf("a = %d, b = %d\n", a, b);
}
结果输出:
a = 100, b = 10
a = 10, b = 100
其次,是引用作为返回值的案例:
引用作为返回值通常指的是函数返回一个引用类型的值,而不是实际的数据副本。这种方式可以用于多种目的,比如节省内存、避免不必要的数据复制、允许函数修改调用者提供的数据等。
#include <iostream>
class MyClass {
public:
int value;
MyClass(int v) : value(v) {}
};
MyClass& getReference(MyClass& obj) {
return obj;
}
int main() {
MyClass obj(5);
MyClass& ref = getReference(obj); // ref是obj的引用
ref.value = 10; // 修改ref实际上修改了obj
std::cout << "obj.value = " << obj.value << std::endl; // 输出:obj.value = 10
return 0;
}
注意事项:
- 生命周期:返回引用时需要确保引用的数据在函数外部使用时仍然有效,否则可能会引发悬空引用的问题。
- 线程安全:在多线程环境中,返回引用可能需要额外的同步机制来保证数据的一致性。
2. C++引用和指针的区别
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
3. 引用的特点小结
- 引用变量的类型必须与它的实体类型一致(因为取别名要符合引用实体的身份,如果类型不一致则会报错)
- 引用变量使用必须要进行初始化(不然没有实体都不知道给谁取别名)
- 一个变量可以有多个引用(就相当于一个变量有好几个别名,这是可以的)
- 引用一旦引用一个实体,再不能引用其他实体(同一个别名不能引用不同的人,否则就分不清谁是谁了)
- 引用不是指针,他就是一个变量,仅仅是一个别名