引用
引用:引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。对引用的操作与对变量直接操作是完全一样的。
引用的声明方法:类型&引用变量名 = 已定义过的变量名
引用的特点:
1.一个变量可取多个别名
2.引用必须初始化
3.引用只能在初始化的时候引用一次,不能改变为再引用其他的变量。
引用用法
void Test1()
{
int a = 1;
int& b = a;
cout << "a:address->" << &a << endl;
cout << "b:address->" << &b << endl;
}
const引用
const引用:是指向const的引用,const引用可以与常量绑定,也可以与变量绑定,只是不能通过这个const引用来改变绑定对象的值。
void Test2()
{
int d1 = 4;
const int& d2 = d1;
cout << "d1:" << d1 << endl;
cout << "d2:" << d2 << endl;
d1 = 5;//d1改变d2也会改变
//d2 = 6; //错误。不能给const修饰的变量赋值
cout << "d1:" << d1 << endl;
const int d3 = 1;
const int& d4 = d3;
cout << "d3:" << d3 << endl;
cout << "d4:" << d4 << endl;
//int& d5 = d3; //错误
const int& d6 = d3; //常量具有常性,只有常引用才可以引用常量
cout << "d6:" << d6 << endl;
double d7 = 1.1;
//int& d8 = d7; //错误
const int& d9 = d7;
//d7是double类型,d8是int,d7赋值给d8时要生成一个临时变量,
//也就是说d8引用的是这个带有常性的临时变量,所以不能赋值。
cout << "d7:" << d7 << endl;
cout << "d9:" << d9 << endl;
}
const引用:范围只能缩小,不能放大。可读可写可变为只读,只读不能变为可读可写。
引用做参数
1.值传递:如果形参为非引用的传值方式,则生成局部变量接收实参的值。值传递指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
void Swap(int left,int right)
{
int tmp = left;
left = right;
right = tmp;
}
2.引用传参如果形参为引用类型,则形参是实参的别名。就相当于实参的交换
void Swap(int& left,int& right)
{
int tmp = left;
left = right;
right = tmp;
}
3.指针传递
void Swap(int* left,int* right)
{
int tmp = *left;
*left = *right;
*right = tmp;
}
测试传值和引用传递的效率
struct Bigdata
{
Bigdata(){
memset(arr, '0', sizeof(arr));
}
int arr[1000];
};
void Deal(Bigdata& x)
{
x.arr[0] = 0;
x.arr[1] = 1;
x.arr[2] = 2;
}
void Test3()
{
Bigdata bd;
int begin = GetTickCount();
for (int i = 0; i < 1000000; ++i){
Deal(bd);
}
int end = GetTickCount();
cout << "cost time:" << end - begin << endl;
}
传值:
传引用:
一定程度上,传引用要比传值快。
指针传递的本质:
指针传递本质上是传值的方式,它所传递的是一个地址值。值传递的过程中,被调用函数的形参作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来形参的值,从而形成了实参的一个副本。
指针传递与引用传递的区别:
引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。
传值做返回值 传参做返回值
//int Add(int d1,int d2){
int& Add(int d1, int d2){
int ret = d1 + d2;
return ret;
}
void Test4(){
int a = 3;
int b = 4;
int c = Add(a, b);
cout << "c:" << c << endl;
}
结论:
- 不要返回一个临时变量的引用 。再调用函数时,会形成栈帧。在返回时,形成临时变量返回,而这个临时变量在栈中。调用结束时,栈被销毁,临时变量也被销毁。
如果返回对象出了当前函数的作用域依旧存在,则最好使用引用返回,因为这样更高效。
引用与指针的区别与联系
1.引用只能在定义的时候初始化一次,之后不能改变指向其它变量;指针变量的值可变。
2.引用必须指向有效的变量,指针可以为空。
3.sizeof指针对象和引用对象的意义不一样。sizeof引用得到的是所指向的变量的大小,而sizeof指针是对象地址的大小。
4.指针和引用自增自减意义不一样。指针++是加上其指向类型的大小。
5.相对而言,引用比指针更安全。注意:指针比引用更灵活,但也更危险。使用指针时一定要注意检查指针是否为空。指针所指的地址释放后最好置为0,否则可能存在野指针问题。