C++的传值、传地址、传引用介绍
C++中支持三种参数传递方式:
1) 按值传递(pass by value) value
2) 地址传递(pass by pointer) *value
3) 引用传递(pass by reference) &value
指针:指针是一个变量,只不过这个变量中存储的是一个地址,指向内存中的一个单元。
引用:引用和原变量是同一个东西,只不过是原变量的一个别名。引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
函数传参的三种方式:
传值:形参是实参的拷贝,改变形参的值并不会影响外部实参的值。实参和形参是处于两个不同的地址空间,传递的实质是将原函数中实参变量的值,复制到被调用函数形参所在的存储空间中。这个形参的地址空间在函数执行完毕后,会被回收掉。整个被调用函数对形参的操作,只影响形参对应的地址空间,不影响原函数中变量的值,因为这两个不是同一个存储空间。
即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。
传指针:形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作——在函数中对指针变量的操作,就是对实参(指针变量地址)所对应的变量的操作,函数调用结束后,原函数中的变量的值将会发生改变。被调用函数中对形参指针所指向的地址中内容的任何改变都会影响到实参。
传引用:形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作。引用和原变量是同一个东西,只不过是原变量的一个别名。在被调用函数中,对引用变量的所有操作等价于对实参的操作。这样,整个函数执行完毕后,原先的实参的值将会发生改变。
传递引用给函数与传递指针的效果是一样的。
函数传参的三种方式例子
#include<iostream>
using namespace std;
//值传递
void change1(int n){
cout<<"值传递--函数操作地址"<<&n<<endl; //显示的是拷贝的地址而不是源地址
n++;
}
//引用传递
void change2(int & n){
cout<<"引用传递--函数操作地址"<<&n<<endl;
n++;
}
//指针传递
void change3(int *n){
cout<<"指针传递--函数操作地址 "<<n<<endl;
*n=*n+1;
}
int main(){
int n=10;
cout<<"实参的地址"<<&n<<endl;
cout<<"--------"<<endl;
change1(n);
cout<<"change1()调用后 n="<<n<<endl;
cout<<"--------"<<endl;
change2(n);
cout<<"change2()调用后 n="<<n<<endl;
cout<<"--------"<<endl;
change3(&n);
cout<<"change3()调用后 n="<<n<<endl;
return true;
}
运行之,输出如下:
实参的地址0x6ffe0c
--------
值传递--函数操作地址0x6ffde0
change1()调用后 n=10
--------
引用传递--函数操作地址0x6ffe0c
change2()调用后 n=11
--------
指针传递--函数操作地址 0x6ffe0c
change3()调用后 n=12
引用和指针的区别与联系:
1.相同点:
底层的实现方式相同,都是按照指针的方式实现的。
2.不同点:
引用定义的时候必须初始化,指针可以不用初始化;
引用一旦初始化为指向一个对象,就不能再指向其他对象,而指针可以在任何时候指向任何一个同类型的对象;
没有空引用,但是有空指针;
在sizeof中的含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节的个数(在32为平台下,指针求sizeof永远是4);
引用++改变的是变量的内容,指针++改变的是指针的指向;
有多级指针,没有多级引用;
引用使用起来比指针安全;
如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏;
待续