C++中的引用
变量名:
变量是一段连续存储空间的别名
程序中通过变量来申请并命名存储空间
通过变量的名字可以使用存储空间
C++中新增加了引用的概念
引用可以看做一个已定义变量的别名
引用语法:Type& name = var;
普通引用在声明时必须用其他的变量进行初始化,两者的地址相同,不能使用常量进行初始化(const除外)
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 4;
int& b = a;
b = 5;
printf("a = %d\n", a);//a = 5
printf("b = %d\n", b);//b =5
printf("&a = %08X\n", &a);//&a = 0x0028FF18
printf("&b = %08X\n", &b);//&b = 0x0028FF18
printf("Press enter to continue ...");
getchar();
return 0;
}
引用的意义:
引用作为其他变量的别名而存在,因此在一些场合可以替代指针
引用相对于指针来说具有更好的可读性和实用性
引用和指针的区别:
引用是某块内存的别名;指针指向一块内存,它的内容是所指内存的地址
引用只能在定义时被初始化一次,之后不可变;指针可变
引用不能为空,指针可以为空;
“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
指针和引用的自增(++)运算意义不一样;
#include <stdio.h>
void swap(int& a, int& b)
{
int t = a;
a = b;
b = t;
}
int main(int argc, char *argv[])
{
int a = 4;
int b = 5;
swap(a, b);
printf("a = %d\n", a);//a = 5
printf("b = %d\n", b);//b = 4
printf("Press enter to continue ...");
getchar();
return 0;
}
引用作为函数参数的时候,可以不进行初始化
const引用
在C++中可以声明const引用
const Type& name = var
const 引用让变量拥有只读属性,不能作为左值
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 4;
const int& b = a;
int* p = (int*)&b;
//b = 5; 报错,不能做左值
*p = 5;
printf("a = %d\n", a);//a = 5
printf("b = %d\n", b);//b = 5
printf("Press enter to continue ...");
getchar();
return 0;
}
当使用常量对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名
#include <stdio.h>
int main(int argc, char *argv[])
{
const int& b = 1;//可以使用常量对常引用进行初始化,编译器为1分配了int空间,b是四个字节连续空间的别名
//int& b = 1;//使用常量对一般引用进行初始化会报错
int* p = (int*)&b;//说明b是只读变量
//b = 5;
*p = 5;
printf("b = %d\n", b);//b是只读变量,所以不在符号表中取值,如果是const int b =1,那么会在符号表中取值,打印b =1
printf("Press enter to continue ...");
getchar();
return 0;
}
const引用可以绑定不同类型的对象和右值。
非const引用只能绑定与对象同类型的对象且不能绑定const对象和右值。
char c = 'c';
char& rc = c;
const int& trc = c
相当于:
int temp = c;
const int &trc = temp;
引用有自己的存储空间吗???
#include <stdio.h>
struct TRef
{
int& a;
int& b;
};
int main(int argc, char *argv[])
{
printf("sizeof(TRef) = %d\n", sizeof(TRef));//打印8
printf("Press enter to continue ...");
getchar();
return 0;
}
事实证明是有的……WHY?
引用在C++中的内部实现是一个常指针
Type& name<---->Type* const name
注意:C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同
从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做出的细节隐藏
void f(int& a){a=5;} 《======》void f(int * const a){ *a = 5; }
#include <stdio.h>
struct TRef
{
int& a;
int& b;
int& c;
};
int main(int argc, char *argv[])
{
int a = 1;
int b = 2;
int c = 3;
TRef rA = {a, b, c};
printf("&a = %08X\n", &a);
printf("&b = %08X\n", &b);
printf("&c = %08X\n", &c);
printf("&rA = %08X\n", &rA);
printf("sizeof(TRef) = %d\n", sizeof(rA));
printf("Press enter to continue ...");
getchar();
return 0;
}
当函数返回值为引用时
若返回栈变量:不能成为其他引用的初始值(局部变量内存被释放),不能作为左值使用
若返回静态变量或全局变量:可以成为其他引用的初始值,即可作为右值使用,也可作为左值使用
#include <stdio.h>
int& f()
{
static int a = 0;
return a;
}
int& g()
{
int a = 0;//会有警告,返回局部变量
return a;
}
int main()
{
int a = g();
int& b = g();
f() = 10;
printf("a = %d\n", a);//a = 0;
printf("b = %d\n", b);//b = -2;因为b是内存空间别名,函数结束,局部变量释放,内存空间也就释放了
printf("f() = %d\n", f());
printf("Press enter to continue ...");
getchar();
return 0;
}
不会干涉编译器的编译行为
所以在C++编译器下面 仍然是C++的行为不会有所改变
标识符的编译方式是指,func(int a, int b)这个函数,在C编译器里面,可能会被编译成_func()
在C++编译器里面,会被编译成_func_int_int
C++就是靠这个方式来区别重载函数的,所以如果用了C的方式,func(int a, int b)和func(char ,int)都是命名成_func,不能区分了,所以不能用