C++初级主题--(4)引用
来源:互联网 发布:angular.js介绍 编辑:程序博客网 时间:2024/05/20 05:04
一.引用的概念
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) }
四.参数传递准则
当给函数传递参数时,人们习惯上通过常量引用来传递。虽然看起来似乎仅是出于效率考虑(通常在设计与装配程序时并不考虑效率),但是这样会带来很多危险。拷贝构造函数需要通过传值方式传递对象,但并不总是可行的
这种简单习惯可以大大提高效率:传值方式会调用构造函数和析构函数,但是如果不想改变参数,则可以通过常量引用传递,它仅需要将地址压栈。
事实上,只有一种情况不适合用传地址方式。就是当传值是唯一安全的途径,否则将会破坏对象时。所以需要依据上下文
- C++初级主题--(4)引用
- C/C++【初级】之一 指针(*)、取地址(&)、解引用(*)与引用(&)的概念
- 11:引用初级使用
- c初级
- C++初级主题--(1)this指针
- C++初级主题--(5)拷贝构造函数
- C++初级主题--(6)赋值函数
- C语言初级问题
- 初级c总结
- C指针初级篇
- C初级程序员劝告
- C语言初级学习
- c语言初级知识点
- C#attribute-----------初级
- Objective-C 初级
- 单链表-C实现-初级
- C语言 - 初级内存
- c语言指针初级
- [vijos1028] 魔族密码
- 向字符变量赋予整数
- PHP程序自杀
- 布局优化偏------------- include、merge 、ViewStub
- 虚拟机安装centos7后出现的问题
- C++初级主题--(4)引用
- [Android 开发工具] 网络抓包Charles
- JavaScript常用对象
- 用Spark Streaming+Kafka实现订单数和GMV的实时更新
- Adaboost算法
- CUDA从入门到精通
- setEnabled() 和 setClickable() 的区别
- linux内核list代码queue.h实现“头插法”
- sonarQube 汉化