首页 > 学院 > 开发设计 > 正文

C++初级主题--(4)引用

2019-11-14 11:39:43
字体:
来源:转载
供稿:网友

一.引用的概念

C++函数中参数的传递方式是传值。在函数域中为参数重新分配内存,而把实参的数值传递到新分配的内存中。它的优点是有效避免函数的副作用(即改变实参的值)。 如果要求改变实参的值,怎么办呢?如果实参是一个复杂的对象,重新分配内存会引起程序执行效率大大下降,怎么办呢?在C++中有一种新的导出型数据类型—引用(reference)可以解决上面的难题。引用又称别名(alias)。

二.传值和传引用的区别

1.用交换程序举例说明 (1)直接通过传值的方式无法更改实参的值

#include<iostream>using namespace std;void swap1(int x, int y){ int tmp = y; y = x; x = tmp;}void main(){ int a = 10; int b = 20; swap1(a,b);}

a,b的值仍未交换,只交换了x,y的值。 这里写图片描述 (2)C语言中通过指针的方式可以交换

#include<iostream>using namespace std;void swap1(int *x, int *y){ int tmp = *y; *y = *x; *x = tmp;}void main(){ int a = 10; int b = 20; swap1(&a,&b);}

可以看到x,y与a,b的地址不同,额外为形参开辟了空间 这里写图片描述 (3)C++中提供引用的方式

#include<iostream>using namespace std;void swap1(int &x, int &y){ int tmp = y; y = x; x = tmp;}void main(){ int a = 10; int b = 20; swap1(a,b);}

可以看到x,y的地址与a,b相同,是a,b的别名,没有重新分配空间。 这里写图片描述

2.总结 (1)传引用可以直接更改实参的值 (2)传引用不用额外分配空间保存实参的数值。 (3)不能定义空引用,即引用的对象必须存在。 3.引用的本质仍是指针 关于这一点,请参考博文 c++ 引用 底层实现机制

引用是在编译的过程中被处理的,实际上就是在编译层面对程序员进行的一个比较友好的语法,而在实现上是由编译器完成了地址的传递,实质上还是指针。 不能简单的理解为一个别名,我们可以这样用,但是要知道底层就是一个指针变量,是要占用内存空间的,和define是不一样的。

三.引用的分类

1.变量的引用

int a = 10;int b = &a;

b是a的引用

2.指针的引用

int a = 10;int *p = &a;int *&q = p;

q是p的引用

3.数组的引用

int ar[10] = {0};int (&br)[10] = ar;

br是ar的引用

4.常量的引用 (1)常量必须用常量引用

const int x = 100;const int &y = x;

(2)变量可以用常量引用

int x = 100;const int &y = x;

(3)不同类型间进行常引用

double x = 13.14;const int &y = x;

这里写图片描述可以看到y与x的地址不同,此时,不同类型之间进行赋值运算,一定会产生临时对象(假设为tmp),最终y是tmp的引用。同时,应注意:对于所有的临时对象,必须同样假设它们是不可存取的,即具有常量的性质。当改变这种数据时,编译器会指出错误,这是非常有用的提示,因为这个改变会导致信息丢失。

5.函数中的引用,即函数返回引用或函数参数中包含引用

(1)最经常看见引用的地方是在函数参数和返回值中。当引用被用作函数参数时,在函数内任何对引用的更改将对函数外的参数产生改变。 (2)当然可以传递一个指针来做相同的事情,但引用具有更清晰的语法。(可以把引用看作一个使语法更加便利的工具。) (3)如果函数返回一个引用,必须像从函数返回一个指针一样对待。当函数返回时,无论引用关联的是什么都应该存在,否则,将不知道指向哪一个内存

int* fun1(int *x) //(2){ (*x)++; return x; //正确,x指向确定的内存} int& fun2(int &x) //(1){ x++; return x; //正确,x指向确定的内存}int& fun3(){ int q; //return q; //错误,局部变量,最终指向不明确的内存 static int p; return p; //正确,尽管fun3运行结束,但是p被static修饰,为全局变量,生存作用域仍存在,指向明确的内存}int main(){ int a = 10; fun1(&a); //ugly(but explicit) fun2(a); //clean(but hidden) }

四.参数传递准则

当给函数传递参数时,人们习惯上通过常量引用来传递。虽然看起来似乎仅是出于效率考虑(通常在设计与装配程序时并不考虑效率),但是这样会带来很多危险。拷贝构造函数需要通过传值方式传递对象,但并不总是可行的 这种简单习惯可以大大提高效率:传值方式会调用构造函数和析构函数,但是如果不想改变参数,则可以通过常量引用传递,它仅需要将地址压栈。

事实上,只有一种情况不适合用传地址方式。就是当传值是唯一安全的途径,否则将会破坏对象时。所以需要依据上下文


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表