C++ 引用
1.基本概念
这里先主要讲左值引用,右值引用还不太懂
引用:其实就是给一个变量起一个“别名”(引用一个“有名字、可寻址”的变量)
例:
int a = 10;
int &ref = a;
在这里,ref 是 a 的别名,对 ref 的操作会直接作用于 a,例如:
ref = 1;
修改了 ref 的值为1,意味着 a 也被修改了。
2 注意事项
2.1 引用必须初始化
创建引用的同时必须对其进行初始化,例如:
int &c; //错误!!!!!!!没有进行初始化int &c = a; //正确,进行了初始化
2.2 引用在初始化后,不可以改变
该引用初始化完成后,它就不能再去引用别的变量了。
通俗地讲:这个别名被用了之后,就不能再换到别人身上了
例:
int a = 10;
int b = 20;int &c = a; //一旦初始化后,就不可以更改
c = b; //这是赋值操作,不是更改引用
上面c=b是一个赋值操作,即令c=a=b=20
3 引用做函数返回值
引用是可以作为函数的返回值存在的
用法:函数调用作为左值
3.1 首先要注意:不能返回局部变量的引用
例如:
int& test01() {int a = 10;return a; // ❌ 错误!x 是局部变量,函数结束后就销毁了
}
因为局部变量函数结束就消失了,引用成野指针
正确的做法是返回静态变量引用,例如:
int& test02() {static int a = 20; //此时a为静态变量,保存在全局区,而不是栈区return a;
}
3.2 其次解释什么是函数调用作为左值
默认情况下,函数调用返回的是右值,比如:
int get()
{ return 10;
}get() = 20; // ❌ 错误,右值不能赋值
上面的普通的函数调用作为左值是错误的
但是当引用作为返回值时,函数调用就可以作为左值,比如:
//返回静态变量引用
int& test02() {static int a = 20;return a;
}int main()
{//如果函数做左值,那么必须返回引用int& ref2 = test02();test02() = 1000; //该操作使静态变量a修改为1000cout << "ref2 = " << ref2 << endl;
}
GPT给的例子更好理解:
int& refFunc(int& x) {return x;
}
//返回的是参数的引用int a = 5;
refFunc(a) = 100; // ✅ 等同于 a = 100;
这就是:“函数调用作为左值”。
3 引用做函数参数+引用的本质
在函数中,可以把引用作为形参
这时候,函数就可以像指针作为形参一样,修改传入实参的值
所以,引用在底层其实就是指针常量的实现,比如:
//自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
int& ref = a;
ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;
4 常量引用
正常来说引用不能直接指向一个常量,但是用 const 修饰引用后就可以,比如:
int& ref = 10; !!!引用本身需要一个合法的内存空间,因此这行错误//加入const就可以了,编译器优底层操作:int temp = 10; const int& ref = temp;
const int& ref = 10;
可以结合前面引用的本质品味一下
常量引用还可以作为参数
作用:常量引用主要用来修饰形参,防止误操作
因为当引用作为函数形参时,可以像指针作为形参一样修改实参的值
因此,可以加 const 修饰引用形参,防止形参改变实参,比如:
//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {v += 10; //❌这样操作会报错,因为用const修饰了形参引用cout << v << endl;
}
解释一下:因为引用的底层
5 还有注意当引用作为重载条件时
上面说过了,常量引用可以直接传入常量
因此在这里就利用这个特性,在引用作为重载条件时作出区分
直接看代码和注释:
void func(int &a)
{cout << "func (int &a) 调用 " << endl;
}void func(const int &a)
{cout << "func (const int &a) 调用 " << endl;
}int main()
{int a = 10;func(a); //调用无constfunc(10);//调用有const}