zoukankan      html  css  js  c++  java
  • C++引用和函数返回值

    这是老师上课讲的内容,现在把它写下来,一方面当做复习,另一方面真的想学点东西。废话不多说,先贴上测试的代码:

     1 #include <iostream.h>
     2 
     3 float temp;
     4 
     5 float fn1(float r)
     6 {
     7     temp = (float)(r*r*3.14);
     8     return temp;
     9 }
    10 
    11 float& fn2(float r)        //绑定return的变量
    12 {
    13     //float temp;
    14 
    15     temp = (float)(r*r*3.14);
    16     return temp;
    17 }
    18 
    19 void main()
    20 {
    21     float a=fn1(5.0);      //
    22     float& b=fn1(5.0);     //VC++ 6.0 error, (有的编译器warning)
    23     float c=fn2(5.0);      //
    24     float& d=fn2(5.0);     //如果temp不是全局变量,仍可能有问题
    25 }

    在分析上面的代码之前,先说两个理论:

    (一)什么是引用。同时借助老师的简单比喻:

    一个变量的引用就是这个变量的别名,引用在定义的时候必须同时初始化。老师是这样比喻的,说他有个同学(具体有无此人,无从考证)个子很矮,所以好多人给老段起了个外号叫做根号2,当然了根号2和老段是同一个人,对老段的任何操作都是对根号2的操作。后来又有人给根号2(也就是老段)起了另一个外号叫做矮冬瓜。这样,根号2、老段和矮冬瓜指的就是同一个人了。这里的老段就象征着变量的本体,根号2就是老段的引用,矮冬瓜就是老段的引用的引用。当然了,这三个称谓表示同一个人。

    (二)一个函数的声明类型和它具体的返回值类型的关系:

    首先知道一点:函数的返回值在内存的栈空间中是要开辟空间的。假设我们给这个空间起个名字叫做END,那么这个END的类型就是函数声明的时候的返回类型,不管你具体实际中返回的是什么类型。例如上面的fn2()函数:

    1 float temp;
    2 float& fn2(float r)        //绑定return的变量
    3 {
    4 
    5     temp = (float)(r*r*3.14);
    6     return temp;
    7 }

    函数返回的时候具体的语法是:float & END = temp;其中float就是这个函数声明时的类型,END就是给函数返回开辟的栈空间,temp就是实际return的东西。这就是用return的temp初始化END引用。这里temp就是老段,END就是根号2。

    ----------------------------------------------------------------------------------------------------------------------------------------

    下面逐个的分析最开始的代码:

    (1)

    1 float a = fn1(5.0);

    函数返回时的语法为:float END= temp;这样END就是一个float类型的变量。上面的这句代码就是用END这个变量初始化a。随后调用结束,栈空间的END就被os收回了。

    (2)

    1 float &b = fn1(5.0);

    END为float类型的,函数返回时具体的语法是:float END= temp;这里的END也是一个float类型的变量。上面的这句代码在main函数中给END弄了一个引用(内部用指针实现的)。这里的b是个引用,也就是根号2,END就是老段。但是问题来了,END是暂时的栈空间啊,函数调用结束后它就被清除了啊,相当于在main函数的栈空间中弄了一个指针,但是这个指针指向了一个即将被清除的变量。当然会报错。

    (3)

    1 float c = fn2(5.0);

    这里的END就是一个引用了,因为fn2声明的时候类型为float &。函数返回时的语法是:float & END = temp;用temp初始化一个引用。这里的END就是根号2,temp就是老段,也就是说对根号2的任何操作都会作用在老段的身上(他们是同一个东西)。所以这个语句的意思就是用temp给c初始化。

    (4)

    1 float &d = fn2(5.0);

    同样END是引用,这里是用一个引用初始化另一个引用。这时temp是老段,END是根号2,d是矮冬瓜,三个名字说的是同一个人。即使调用结束后,END被清掉了,但是他毕竟是别名,不是变量的本尊,所以不会报错。

    -----------------------------------------------------------------------------------------------------------------------------------------

    注:作用在引用上的操作,同样会作用在变量本身上,但是如果这个引用的生存期到了,它要消亡了,这是没有关系的。就好像,忽然有一天大家都不在管老段叫根号2,那么根号2这个外号的生存期就到头了。但是这没什么影响。

    但是老段不能消亡,你说老段消亡了,但是根号2这个外号还在,那不行,根号2指的是谁啊。

    引用理论上是不占内存空间的,但是实际的实现上就是指针的操作。只不过这种指针的操作对编程人员是透明的。

  • 相关阅读:
    jmeter元件的执行顺序
    jmeter json path espressions学习
    性能测试常见瓶颈分析及调优方法
    jmeter 聚合报告参数解释
    Jmeter 使用正则表达式提取响应结果中的值
    前端所需要了解的东西
    webpack4导入jQuery的新方案
    react服务端渲染SSR实战
    使用await写异步优化代码
    Provider
  • 原文地址:https://www.cnblogs.com/stemon/p/3397438.html
Copyright © 2011-2022 走看看