临时对象问题

http://topic.csdn.net/t/20060412/19/4682278.html

比如我重载了+运算符,然后返回integer对象  
  return   integer   (left.i   +   right.i)   ;  
  书上说:"这样情况时,编译器明白对创建的对象没有其他需求,只是返回它,所以编译器直接地把这个对象创建在返回值外面的内存单元。因为不是真正创建一个局部对象,所以仅需要单个的普通构造函数调用(不需要拷贝构造函数),并且不会调用析构函数。因此,这种方法不需要什么花费,效率是非常高的。  
   
  我的问题是:1.里面说指的外面的内存单元指的是什么?  
  2.既然调用了普通的构造函数,为什么退出作用域时不会调用析构函数?

>>>>>>>  answer

首先要知道临时类如何使用  
   
  比如:  
  class   MyInt  
  {  
  public:  
          MyInt()         {   printf("Constructing...\n");   }  
          ~MyInt()       {   printf("Destructing...\n");     }  
  };  
   
  然后使用以下测试代码:  
  MyInt   GetMyInt()  
  {  
          return   MyInt();  
  }  
   
  int   main(int   argn,   char   *argv[])  
  {  
          GetMyInt();  
          printf("Done   of   GetMyInt().\n");  
          return   -1;  
  }  
  运行后你应看到以下结果:  
  Constructing...                                               //   在函数GetMyInt()中  
  Destructing...                                                 //   在函数main()中  
  printf("Done   of   GetMyInt().\n");             //   在函数main()中,GetMyInt()后  
   
  也就是class   MyInt的实例的确存在过,并且曾经构造并析构。  
  实际上,在GetMyInt()返回时,return会在堆栈中找到返回内存,并以此调用构造函数;在返回以后,main使用完毕了此类(本例中并没有任何使用)后,调用了类的析构函数,然后继续。  
   
  所谓的外面的内存,实际上就是指上一级函数栈的空间,也就是承载返回值的空间,一般来说,返回值都是使用寄存器(如x86上一般都使用ax/eax/rax),但是如果返回的是结构、类,则是内存。  
   
  +------------------+-----------------------+--------------+  
  |   GetMyInt()   stack   |   GetMyInt()   parameters   |   main()   stack   |  
  +------------------+-----------------------+---------------  
  在return时,前面的stack   &   parameters都会被弹出(add   esp,   xxx),然后再保留一个空间作为返回值(sub   esp,   sizeof(class   MyInt)),然后以esp为指针构造类。返回以后,main可以直接使用并在使用完毕以后析构。  
   
  为了进一步分析,采用以下例子:  
   
  class   MyInt  
  {  
  public:  
          MyInt()         {   printf("Constructing...\n");   }  
          ~MyInt()       {   printf("Destructing...\n");     }  
          operator   +(class   MyInt   &m2)   {   printf("Add!\n");   };  
  };  
   
  MyInt   GetMyInt()  
  {  
          return   MyInt();  
  }  
   
  int   main(int   argn,   char   *argv[])  
  {  
          GetMyInt()   +   GetMyInt();  
          printf("Done   of   GetMyInt().\n");  
          return   -1;  
  }  
   
  运行以后应该看到:  
  Constructing...                                 //   第一次调用GetMyInt()函数内  
  Constructing...                                 //   第二次调用GetMyInt()函数内  
  Add!                                                       //   main()函数内  
  Destructing...                                   //   main()函数内,表达式完毕  
  Destructing...                                   //   main()函数内,表达式完毕  
  Done   of   GetMyInt().  
  看到此例的结果,应该明白构造、析构的情况。  
   
  关于栈的情况,可以将类的构造函数修改为:  
          MyInt()         {   int   _esp;   __asm   {   mov   _esp,   esp   };   printf("Constructing...   %p,   esp   =   %p\n",   this,   _esp);   }  
   
  运行后,结果类似如下(具体值会有不同,和机器、编译器、操作系统相关)  
  Constructing...   0012FF6C,   esp   =   0012FE58  
  Constructing...   0012FF70,   esp   =   0012FE54  
  Add!  
  Destructing...  
  Destructing...  
  Done   of   GetMyInt().  
  可以注意到,两次construct的this地址偏移差是sizeof(MyInt),和esp相当接近(不会相等,因为构造函数本身也需要使用栈)  

原文地址:https://www.cnblogs.com/carl2380/p/1924606.html