博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如果返回结构体类型变量(named return value optimisation,NRVO) ------ 续
阅读量:7079 次
发布时间:2019-06-28

本文共 8734 字,大约阅读时间需要 29 分钟。

为什么?

《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 : 0xbff65e4ctemp 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 : 0x84f1008copy constructor this : 0xbfa6386cthiz : 0x84f1008temp this : 0xbfa6386cdeconstructor 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 : 0xbf8594ccdeconstructor this : 0xbf8594cccopy constructor this : 0xbf8594fc  //显然错了thiz : 0xbf8594cctemp this : 0xbf8594fcdeconstructor 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)。

我错过了比赛……

你可能感兴趣的文章
Centos7
查看>>
cisco *** 学习笔记--第四天
查看>>
2014第2周
查看>>
删除N天前日志
查看>>
my.cnf 详解与优化
查看>>
我的友情链接
查看>>
二维指针——改变动态申请的空间大小
查看>>
静态路由实验题
查看>>
NTP white paper
查看>>
Cisco 3750 802.1x认证失败跳转vlan的配置
查看>>
Binary indexed tree
查看>>
etcd的学习心得和使用
查看>>
企业邮箱发邮件出现系统退信(NDR)的大致原因?
查看>>
js封装对象——prototype的使用
查看>>
html5 web worker 011
查看>>
alternatives(update-alternatives) 的配置目录位置
查看>>
SSO:JWT安全认证的应用问题
查看>>
前端:可视化数据分析探索之Canvas与SVG
查看>>
我的友情链接
查看>>
cisco设备配置时间日期的方法。
查看>>