zoukankan      html  css  js  c++  java
  • C/C++ ===复习==函数返回值问题(集合体==网络)

    按值传递

    地址传递:

    应该明白只有这2种传递,下面讨论函数的按值传递

    #include <stdio.h>
    #include <stdlib.h>
    int add_rtVal(int a,int b)
    {
        int c = 0;
        c = a + b;
        return c;
    }
    int main(int argc,char* argv[])
    {
        int a = 0,b = 0;
        int c = 0;
        a = 3;
        b = 5;
        c = add_rtVal(a,b);
        printf("c=%d/n",c);
        
        return 1;
    }

    这个地方是正确返回了,测试c也对,why?我们返回的是一个值 ,在返回值后我们将其赋给了变量C,相当于创建了一个副本,不论add()中的局部变量是否销毁都没有关系了。

     但是如果我们返回的是一个地址,指向局部变量的地址,就不行了。因为局部变量的地址在函数调用完成后销毁,我们返回的地址就指向的区域内就不是我们想要的值了,因为这块区域已是公共的,可被其它函数占用的,其内容是不定的。看如下例子:

    #include <stdio.h>
    #include <stdlib.h>
    char* hello()
    {
        char p[]= "hello world";
        return p;
    }
    int main(int argc,char argv[])
    {
        char *str;
        
        str = hello();
        printf("%s/n",str);
        return 1;
    }

    结果:"/n
    Process returned 1 (0x1) execution time : 0.094 s
    Press any key to continue.

    ====================================================================================

    #include<iostream>
    int a,i;
    int fun()
    {
      int b=1,c=2;
      a=b+c;
      return a;
    }
    i=fun()
    首先,这里必须是传递a的副本
    其次,为什么传递副本,不是由a的生命周期来定义的,比如a是否是全局,或者局部,甚至是static,都与是否传递副本没有关系的
    最后,这里传递副本是取决于fun函数的,fun函数返回的类型是 int,也就是说返回值的传递时采用 ” 值传递 “,你应该懂这个名词,不是地址传递,而值传递,明显特征是要传递副本
    换句话说,如果定义fun函数如下:
    int& fun();
    那么可以return a,不会有副本产生。注意必须是a为全局的情况下,否则会引起警告,禁止传递局部变量的引用,因为a的声明周期会马上结束掉。

    ???为什么不写成int& fun();这种形式呢?答案是没必要。int是内部自定义类型。对于自定义变量而言,引用与否引起的副本拷贝带来的工作量不是很大,相反,如果是自定义类型,不知道楼主学习了class没有,那么引用返回就非常有必要了。
    因为带来的副本拷贝可能非常耗时,而这也是C++之父strup反复强调了,也是我们需要常常使用的
    void   function(int   a) <-这里是传值调用,所以要建立一个参数的副本再传给函数 
    
    这样一来a这个参数的原始数据就会保留,不会在函数中被改变: 
    
    void   function(int   a) 
    { 
              a++; 
    } 
    这里如果a=1;函数执行完毕后a还是等于1. 
    
    void   function(int   &a) <-这里是模拟一个指针,当编译器编译这个函数的时候,直接到a的地址去操作a,这样避免了产生一个副本可能带来的额外开销.但是增加了危险性
    
    void   function(int   &a) 
    { 
              a++; 
    } 
    如果a的原始数据是1的话,那么a++后a的数据将变成2 
    不管a是全局变量还是局部变量

    下面我们再看一种情况,这是返回引用给变量的情况:
    
    #include <iostream>    
    #include <string>    
    using namespace std;  
      
    float c;  
    float& test(float,float);  
    void main(int argc,char* argv[])      
    {  
        float pn=test(3.0f,1.2f);  
        cout<<pn;  
        cin.get();  
    }  
      
    float &test(float a,float b)  
    {  
        c=a*b;  
        return c;  
    }
      这种返回引用给变量的情况下,在内存中,test()所在的栈空间内并没有产生临时变量,而是直接将全局变量c的值给了变量pn,这种方式是我们最为推荐的操作方式,因为不产生临时变量直接赋值的方式可以节省内存空间提高效率,程序的可读性也是比较好的。
    #include <iostream>    
    #include <string>    
    using namespace std;  
      
    float c;  
    float& test(float,float);  
    void main(int argc,char* argv[])      
    {  
        float &pn=test(3.0f,1.2f);  
        cout<<pn<<endl;  
        test(3.0f,1.2f)=12.1;//把函数作左值进行计算!  
        cout<<pn;  
        cin.get();  
    }  
      
    float &test(float a,float b)  
    {  
        c=a*b;  
        return c;  
    }
      通常来说函数是不能作为左值,因为引用可以做为左值,所以返回引用的函数自然也就可以作为左值来计算了。
    
      在上面的代码中:
    
    float &pn=test(3.0f,1.2f); 
    
      进行到这里的时候pn已经指向到了目标c的地址了。 
    
      接下来运行了 
    
    test(3.0f,1.2f)=12.1; 
    
      把函数作左值进行计算,这里由于test是返回引用的函数,其实返回值返回的地址就是c的地址,自然c的值就被修改成了12.1
  • 相关阅读:
    榨干PHP性能的使用细节
    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
    Oracle 表锁处理总结
    Windows安装NodeJS
    RedHed5.8 重装yum
    linux Redhat5.8 升级 openSLL 无法升级成功,解决办法
    idea安装详情
    Linux升级OpenSSH 和 OpenSSL 详细步骤
    Oracle dmp文件 exp导出,imp导入
    redis哨兵模式增加密码认证
  • 原文地址:https://www.cnblogs.com/qbmiller/p/3795048.html
Copyright © 2011-2022 走看看