为什么?

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

 Number Number::makeReal(double r){Number tx; return tx}

 main:

       Number t = Number::makeReal();

   自己想的应该是:先生成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();
cout << "temp this : " << &temp << endl;
return ;
}

//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();
cout << "temp this : " << &temp << endl;
return ;
}

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

我错过了比赛……

最新文章

  1. EF CodeFirst EntityTypeConfiguration 自关联映射配置
  2. [转载]Python中的sys模块
  3. PageObject小结
  4. Atitit 常见的树形结构 红黑树 &#160;二叉树 &#160;&#160;B树 B+树 &#160;Trie树&#160;attilax理解与总结
  5. string.Format出现异常&quot;输入的字符串格式有误&quot;的解决方法
  6. uart与usart
  7. http://www.myexception.cn/program/767123.html
  8. 在Tomcat中部署Java Web应用程序
  9. poj1664 (递归)
  10. HDOJ(HDU) 2103 Family planning(需要注意范围)
  11. Spring AOP那些学术概念—通知、增强处理连接点(JoinPoint)切面(Aspect)
  12. URLencode 特殊字符 转义 遇上的坑
  13. php 7 event 安装
  14. java基础-位运算符
  15. Hybrid设计--账号体系的建设
  16. 关于RNA-Seq数据去接头(Adapter)这事需要讲一讲
  17. printf中用法详解
  18. LOCAL_LISTENER 引起的错误
  19. kafka linux 启动脚本 sample
  20. ios两视图间托付(delegate)传值

热门文章

  1. scala工程导入报错:scalatest_2.10-1.9.1.jar is cross-compiled with an incompatible version of Scala (2.10).
  2. BAT-增加JAVA环境变量(WIN764位)
  3. js 删除数组几种方法
  4. WebSphere ILog JRules 域的介绍和定制
  5. cacti监控jvm
  6. OpenCV颜色空间——HLS颜色空间
  7. Java编程的逻辑 (43) - 剖析TreeMap
  8. js中表单数据序列化方式
  9. sqlserver查看和解除表死锁
  10. ansible示例,离线安装etcd