**
c++中的引用是c++与c不同的一个地方,也是c所没有的。**
什么是引用?
引用不是新定义一个变量,而是给已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用一块内存空间
举个例子:
王小明是一个人,“王小明”就是他的名字,但是在家他妈可能会叫他 “小明”,这个 “小明” 就相当于一个别名,也就是引用。
基本语法:
类型 & 引用变量名(对象名) = 引用实体。
int main() {
int a = 10;
int& ra = a; // 定义引用类型
//ra就是a的引用 , 也就是a的别名。
cout << "a的地址:" << &a << endl;
cout << "ra的地址:" << &ra << endl;
return 0;
}
这也印证了编译器并没有为ra单独开辟空间,而是用和a一样的空间。
引用的特性:
1.引用在定义时必须初始化!
int a = 10;
int& ra ; //这是不被允许的!
2.一个变量可以有多个引用
相当于你可以有很多个外号,别名,不冲突.
3 引用一旦引用一个实体,再不能引用其他实体!
int main() {
int a = 10;
int& ra = a; // 定义引用类型
//ra就是a的引用 , 也就是a的别名。
int b = 20;
// &ra = b; 这是不被允许的
ra = b; // 相当于将b的值赋给 ra 也就是 a
return 0;
}
常引用:
int main() {
const int a = 10;
int& ra = a; //该语句编译时会报错
return 0;
}
int main() {
const int a = 10;
const int& ra = a;
//这样是没问题的
return 0;
}
int main() {
double a = 1.22;
int& ra = a;
//这样也会报错,a为double,b为int,无法修改a的值
return 0;
}
int main() {
double a = 1.22;
int& ra = 10;//会报错,引用常数10,但是10不可修改的
return 0;
}
int main() {
double a = 1.22;
const int& ra = 10; //不会报错
const int& rra =a ;//也不会报错
return 0;
}
总结:
1.const 会改变变量权限,将原来的变量又 可读可写 变为 只能读不能写。
2.当引用变量与原变量不同,或引用了常数时,应当加上const,因为改变量是不可写的。
3.对原引用变量,权限只能缩小,不能放大。
使用场景:
1.做函数的参数:
void swap(int& x, int& y) {
int tmp = x;
x = y;
y = tmp;
}
int main() {
int x = 10;
int y = 20;
swap(x, y);
cout << "x:" << x << endl;
cout << "y:" << y << endl;
return 0;
}
这里我们不需要指针就完成了两个变量的交换。
void swap(double& x, double& y) {
double tmp = x;
x = y;
y = tmp;
}
因为c++支持函数的重载,配合引用,让我们更加方便。
2.做返回值
int count() {
int n = 0;
++n;
return n;
}
int main() {
int ret = count();
cout << "ret:" << ret << endl; // ret : 1;
return 0;
}
当函数返回值时,该返回值会被储存在一个临时变量中。
int count() {
int n = 0;
++n;
return n;
}
int main() {
const int& ret = count(); // 前面一定要const, 因为count()的返回值储存在一个临时变量里,临时变量具有常性,无法修改。!
cout << ret << endl; //
return 0;
}
int& count() {
int n = 0;
++n;
return n;
}
int main() {
int& ret = count();
cout << ret << endl; // ret 的值是1
cout << " " << endl; //
cout << ret << endl; //ret是随机值
return 0;
}
由上述代码我们可以得知,当你的函数返回值是引用返回时,是没有临时变量的,此时你的ret有点类似与野指针了,count()的那块空间已经还给内存了,但是为什么会有一个是1 一个是随机值的情况呢?
其实是这样的:再执行完语句 int& ret = count(); 后,count函数的函数栈帧已经还给内存,但是此时没有其他函数覆盖该空间,所以ret的值仍然是1,但是 当执行了语句 cout << " " << endl; 后, cout会覆盖原来的函数栈帧,让ret变为随机值
int& count() {
static int n = 0;
++n;
return n;
}
int main() {
int& ret = count();
cout << ret << endl; // ret 的值是1
return 0;
}
但当n变为static修饰的静态变量时,引用传值就不会出现上述的问题。
注意: 如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回!
传值,传引用效率的比较
简单一句话:传值效率比传引用效率低,且数据量越大越明显
引用和指针的区别:
1 引用定义时必须初始化,指针不一定。
2 引用在初始化一个实体后,就再也不能引用其他实体,而指针可以在任何时候指向任何一个同类型的实体。
3 没有NULL引用,只有NULL指针
4在sizeof中,引用为引用类型的大小,而指针大小永远都是地址空间所占字节数(32为平台 4字节)
5有多级指针,但没有多级引用
6引用比指针更加安全
注意: 引用和指针在底层的实现上是一样的,引用时按照指针方式来实现的。
(可以参考他们的汇编代码)