c++超细致讲解引用
引用的概念引用 不是新定义一个变量而 是给已存在变量取了一个别名 编译器不会为引用变量开辟内存空间它和它引用的变量共用同一块内存空间。引用的表示方法类型 引用变量名 ( 对象名 ) 引用实体如果熟悉C语言的同学可能会发现引用符号()看上去就像取地址运算符()或者按位AND运算符()其实这是一个运算符重载的例子。通过重载同一个运算符将会有不同的含义。编译器会通过上下文来确定运算符的含义。除了这里所提到的其实在C中还有一些运算符重载的情况。例如* 即表示乘法又表示对指针的解引用操作即表示插入运算符又表示按位左移运算符等。代码实例12345678intmain(){//引用取别名inta 10;int b a;//定义引用类型int c b;return0;}本段代码我们可以得知a变量取了bc两个别名。我们也可以通过调试观察他们的内存通过调取内存我们可以发现a,b,c所指向的是同一块内存空间。注意 引用类型 必须和引用 实体 是 同种类型 的引用特性引用有三个特性分别是1. 引用在 定义时必须初始化2. 一个变量可以有多个引用3. 引用一旦引用一个实体再不能引用其他实体1.引用在定义的时候必须初始化由于引用是对已经存在的变量进行取别名因此使用引用时必须指定变量(初始化)。1int d;//错误未初始化2.一个变量可以有多个引用在C语法中一个变量有多个引用就类似于一个人可以有多个外号。在1.1的代码实例中变量a就有2个引用分别是b和c。3.引用一旦引用一个实体再不能引用其他实体这个也比较好理解因为引用一旦引用了一个已经存在的实体就是这个实体的别名当然不能再成为其他实体的别名。常引用与引用权限我们来观察下面这段代码他能编译成功吗1234567intmain(){//1.constintx 20;int y x;return0;}当我们编译这段代码发现编译器报出错误警告无法从“const int”转换为“int ”这是因为我们在引用的时候要遵守引用的原则引用原则:对原变量的引用权限不能放大。1.3这段代码中x变量是const修饰是一个常变量只有可读权限。而我们引用的类型是int不仅有可读权限还有可修改权限。这就造成了对原变量的权限放大。根据我们引用原则知道对原变量的引用权限是不能放大的这就是为什么这段代码会报错的原因。那我们再来看这一段代码它能编译成功吗12345678910intmain(){//2.constintx 20;constint y x;//不变//3.intc 30;constint d c;//缩小return0;}这段代码我们发现编译成功了我们也可以轻松地分析出这里的引用是遵守引用规则的我们发现权限不变或者权限缩小都是符合规则的唯一需要注意的是权限不能放大。引用的使用场景做参数123456789101112voidSwap(int x,int y){inttmp x;x y;y tmp;}intmain(){inta 0, b 1;Swap(a, b);return0;}引用可以作函数的形参x是a的别名y是b的别名。这里使用引用更加方便也更好理解。那既然以值作为函数参数和以引用作为函数参数都能解决这个问题那为什么还要使用引用来做参数呢这是因为引用的效率更高我们可以通过下面这段测试代码更加直观看出效率的差别1234567891011121314151617181920212223242526#include time.hstructA {inta[10000]; };voidTestFunc1(A a) {}voidTestFunc2(A a) {}voidTestRefAndValue(){A a;// 以值作为函数参数size_tbegin1 clock();for(size_ti 0; i 10000; i)TestFunc1(a);size_tend1 clock();// 以引用作为函数参数size_tbegin2 clock();for(size_ti 0; i 10000; i)TestFunc2(a);size_tend2 clock();// 分别计算两个函数运行结束后的时间cout TestFunc1(A)-time: end1 - begin1 endl;cout TestFunc2(A)-time: end2 - begin2 endl;}intmain(){TestRefAndValue();return0;}我们发现使用引用作为函数参数效率大大提高。以值作为参数或者返回值类型在传参和返回期间函数不会直接传递实参或者将变量本身直接返回而是传递实参或者返回变量的一份临时的拷贝因此用值作为参数或者返回值类型效率是非常低下的尤其是当参数或者返回值类型非常大时效率就更低。引用做参数的意义1.输出型参数。2.减少拷贝提高效率。做返回值首先我们来观察这段代码的返回值是什么?12345678910111213intCount(){staticintn 0;n;returnn;}intmain(){cout Count() endl;cout Count() endl;cout Count() endl;return0;}这里的结果是1 2 3因为n是局部静态的成员变量只会初始化一次虽然作用域在Count函数内部但是生命周期是全局我们可以通过调试观看他是否再执行函数的第一句传值的底层过程传值返回这个过程当中会产生一个临时变量跟传参一样如果小会用寄存器替代。传值返回的类型其实是临时变量的类型将n拷贝给临时变量再将临时变量拷贝给ret。那么为什么要设计临时变量呢直接把n给ret不好吗这是因为在当临时变量出了函数作用域之后会销毁函数栈桢也会销毁那么此时n是不能作为返回值再赋值给ret的。那么编译器就在此生成了一个临时变量把n拷给临时变量再把临时变量给ret。此时函数栈桢销毁是不会影响临时变量的。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2565957.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!