引用和指针的区别
(1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。
(2) 引用不可以为空,当被创建的时候,必须初始化,初始化后就不会再发生改变;而指针可以是空值,可以在任何时候被初始化,指针的值在初始化后可以改变,即指向其它的存储单元。
(3) 可以有const指针,但是没有const引用;
(4) ”sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小;
(5) 从内存分配上看,程序为指针变量分配内存区域,而不为引用分配内存区域,因为引用声明时必须初始化,从而指向一个已经存在的对象。引用不能指向空值。
1. 指针传递和引用传递
指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值(变量地址值)。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值,也就是改变形参指针指向的地址,不会改变实参指针的地址,如果想通过指针参数传递来改变主调函数中,也就是实参的值,那就得使用指向指针的指针,或者指针引用。但是对形参指向的地址空间改变会影响实参指针指向的地址空间值,因为两者指向的都是同一个内存空间(相同的地址值)
而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
// 指针方式进行交换
// 数值传递,有数值拷贝的过程
void swap1(int* x, int* y) {
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}
// 引用的方式进行交换
// 形参引用的实参,修改形参等价于修改实参
// x 将是a的引用, y将是b的引用
void swap2(int& x, int& y) {
x = x ^ y;
y = x ^ y;
x = x ^ y;
}
int main(void) {
//
int a = 3;
int b = 5;
swap1(&a, &b);
cout << "a=" << a << ", b=" << b << endl;
swap2(a, b);
cout << "a=" << a << ", b=" << b << endl;
}
2. 返回引用和返回指针
引用型返回值,可以将函数返回类型声明为引用型,此时函数返回的就是数据的别名,避免函数返回时的一个空间值拷贝,避免函数返回值的开销。
指针型返回值,可以将函数返回类型声明为指针型,此时函数返回的就是指向数据的指针,指针在返回时会拷贝一份指针变量存放的数据变量地址。
注意:1)可以返回全局变量、静态变量和成员变量的引用;2)可以返回引用型参数的本身;3)可以返回调用对象自身的引用;4)可以返回函数内部动态分配的堆对象的引用;4)不能返回局部变量的引用,因为局部变量空间在函数结束时,会自动释放掉;
参考链接:
[1] https://www.jianshu.com/p/9d4f5ab84d40
[2] https://blog.csdn.net/guaiderzhu1314/article/details/113099091