zoukankan      html  css  js  c++  java
  • 如果返回结构体类型变量(named return value optimisation,NRVO) ------ 续

    为什么?

    《More C++ idioms》: 3. Algebraic Hierarchy
     程序执行的流程与自己想的不一样:  

     Number Number::makeReal(double r){Number tx; return tx}
    
     main:
    
           Number t = Number::makeReal(10);
    
       自己想的应该是:先生成tx(默认构造); 返回时需要一个临时量temp,并以tx初始化(拷贝构造),而后用temp初始化 t (拷贝构造);
    
       实际执行流程是:生成tx(默认构造),tx就是t

    理解好C语言,自然就知道原因了,见:http://www.cnblogs.com/openix/p/3178259.html

    更深入一步:

        如果我们以上面给出的原因链接来 理解:

    《C++ Primer 》4_th_CN p_214 的 “4、千万不要返回局部对象的引用”

       也许我们会认为 第4点有问题,因为按照“C语言”理解,返回的Number实际上就是在main函数中创建的number, 但是我们应该明白 第4点是绝对没错的,原因只有一点:

        当返回引用一定会构建被调用函数的临时量该临时量与发起调用中的被初始量一定不同

    启示:

       返回引用是否一定高效,而直接返回一个结构体是否就一定低效。答案:NO

    对比以下三个程序:

    其中A最高效;B可以完成同样的功能,但是效率太低,而且造成内存泄漏;C根本就是错的(尽管可以完成同样的功能,但是请记住p_214的第4点)

    //A 
    default constructor this : 0xbff65e4c
    temp this : 0xbff65e4c
    deconstructor this : 0xbff65e4c
    
    
    class Base                                                                      
    {                                                                               
        public:                                                                     
            Base(const Base &thiz) : val(thiz.val)                                  
            {                                                                       
                cout << "copy constructor this : " << this << endl;                 
                cout << "thiz : " << &thiz << endl;                                 
            }                                                                       
                                                                                    
            static Base makeBase(int v)                                             
            {                                                                       
                Base temp(v);                                                       
                return temp;                                                        
            }                                                                       
                                                                                    
        private:                                                                    
            int val;                                                                
            Base(int v) : val(v)                                                    
            {                                                                       
                cout << "default constructor this : " << this << endl;              
            }                                                                       
                                                                                    
    };                                                                              
                                                                                    
    int main(void)                                                                  
    {                                                                               
        Base temp = Base::makeBase(3);                                              
        cout << "temp this : " << &temp << endl;                                    
        return 0;                                                                   
    }

    //B 效率太低,而且内存泄漏

    default constructor this : 0x84f1008
    copy constructor this : 0xbfa6386c
    thiz : 0x84f1008
    temp this : 0xbfa6386c
    deconstructor this : 0xbfa6386c  //0x84f1008内存泄漏,即使最后进程终止时未被回收的内存,系统将自动回收,可是我们不应依赖于此行为
    class Base                                                                      
    {                                                                               
        public:                                                                     
            Base(const Base &thiz) : val(thiz.val)                                  
            {                                                                       
                cout << "copy constructor this : " << this << endl;                 
                cout << "thiz : " << &thiz << endl;                                 
            }                                                                       
                                                                                    
            static Base& makeBase(int v)                                            
            {                                                                       
                Base *p = new Base(v);                                              
                return *p;                                                          
            }                                                                       
                                                                                    
            ~Base(void)                                                             
            {                                                                       
                cout << "deconstructor this : " << this << endl;                    
            }                                                                       
                                                                                    
        private:                                                                    
            int val;                                                                
            Base(int v) : val(v)                                                    
            {                                                                       
                cout << "default constructor this : " << this << endl;              
            }                                                                       
                                                                                    
    };

    //C完全就是错的

    In static member function ‘static Base& Base::makeBase(int)’:
    warning: reference to local variable ‘temp’ returned [enabled by default]
    
    
    default constructor this : 0xbf8594cc
    deconstructor this : 0xbf8594cc
    copy constructor this : 0xbf8594fc  //显然错了
    thiz : 0xbf8594cc
    temp this : 0xbf8594fc
    deconstructor this : 0xbf8594fc
    class Base                                                                      
    {                                                                               
        public:                                                                     
            Base(const Base &thiz) : val(thiz.val)                                  
            {                                                                       
                cout << "copy constructor this : " << this << endl;                 
                cout << "thiz : " << &thiz << endl;                                 
            }                                                                       
                                                                                    
            static Base& makeBase(int v)                                            
            {                                                                       
                Base temp(v);                                                       
                return temp;                                                        
            }                                                                       
                                                                                    
            ~Base(void)                                                             
            {                                                                       
                cout << "deconstructor this : " << this << endl;                    
            }                                                                       
                                                                                    
        private:                                                                    
            int val;                                                                
            Base(int v) : val(v)                                                    
            {                                                                       
                cout << "default constructor this : " << this << endl;              
            }                                                                       
                                                                                    
    };                                                                              
                                                                                    
    int main(void)                                                                  
    {                                                                               
        Base temp = Base::makeBase(3);                                              
        cout << "temp this : " << &temp << endl;                                    
        return 0;                                                                   
    }  

    现在我们知道A的效率最高,那么我们是否应该向A这样设计程序,我认为:尽量不要如此,对于Algebraic Hierarchy程序如此设计确实很好,而且使用起来很方便,但是请注意对于A中的makeBase函数,其中只有一个temp变量,因此很容易将main中的t与该变量对应起来,但是如果makeBase中的Base类型变量一旦多起了,编译器自然可以从容应对,但是我们已经不便于我们分析了(因为我们不知是否需要经过一个编译器插入的临时量,并将其通过拷贝构造函数初始化t)。

    我错过了比赛……

  • 相关阅读:
    Linux调试工具
    LINUX总结第13篇:LINUX下动态库及版本号控制
    linux虚拟机无法上网 Network is unreachable
    VMware 如何通过现有虚拟机克隆新的虚拟机 (图文)
    Win10下安装虚拟机提示“Intel VT-x处于禁用状态”如何解决
    VMware安装Centos7超详细过程(图文)
    kubernetes---CentOS7安装kubernetes1.11.2图文完整版
    通过Idea进行Kubernetes YAML开发
    如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes
    SpringBoot + Spring Security 基本使用及个性化登录配置详解
  • 原文地址:https://www.cnblogs.com/openix/p/3416098.html
Copyright © 2011-2022 走看看