【问题标题】:constructor and copy constructor构造函数和复制构造函数
【发布时间】:2013-10-13 13:29:25
【问题描述】:
#include <iostream>

using namespace std;

class t{
private:
int * arr;

public:
    t() { arr=new int[1]; arr[0]=1;}
    t(int x) {arr=new int[1]; arr[0]=x;}
    t(const t &);
    ~t() {cout<<arr[0]<<"   de"<<endl; delete [] arr;}
    t & operator=(const t & t1){arr[0]=t1.arr[0];return *this;}
    void print(){cout<<arr[0]<<endl;}

};
t::t(const t & t1) {arr=new int[1];arr[0]=t1.arr[0];}

int main(){

   t b=5;
   cout<<"hello"<<endl;
   b.print();
   b=3; 
   b.print();
   return 0;
}

为什么是结果

hello
5
3   de 
3
3   de ?

为什么 "t b=5;"不会调用析构函数? “t b = 5”如何工作?它是否首先使用构造函数“t(int x)”创建一个临时对象(t类),然后使用复制构造函数“t(const t &)”创建b? 如果是这种情况,为什么它不调用 temp 对象的析构函数?

【问题讨论】:

    标签: c++ constructor copy-constructor


    【解决方案1】:

    为什么 "t b=5;"不会调用析构函数?

    当你这样做时:

    t b=5;
    

    你会得到copy initialization。语义上调用隐式转换构造函数t(int),然后调用复制构造函数t(const t&amp;)实例化b。但是,允许编译器elide the copy,这就是您的情况。对象是就地构造的,不需要复制构造。这就是您看不到析构函数调用的原因。但是你的类仍然需要一个复制构造函数来编译该代码:复制省略是可选的,并且某些代码是否编译不应该取决于编译器是否执行省略。

    如果你说

    t b(5);
    

    然后将有一个直接初始化,没有复制省略,并且只有一个构造函数调用。您的类不需要复制构造函数来编译此代码。

    【讨论】:

      【解决方案2】:

      由于您没有使用int 的赋值运算符,因此b = 3; 被解释为

      `b.operator=(t(3));`
      

      这会创建一个临时的t 实例,并在分配返回后销毁它。这就是打印第一行 de 的内容。最后,在main 的末尾,b 超出范围,调用其析构函数并打印第二行。

      【讨论】:

      • @juanchopanza 为什么?你认为哪个对象在“你好”之前被破坏了?请注意,t b=5; 不是 赋值,而是初始化。它使用t(int) 构造函数,而不是operator=
      • 对不起,误读了您的答案。我以为你在谈论初始化。
      【解决方案3】:

      也许您的程序中的一点痕迹可以帮助您了解正在发生的事情:

      int main(){
        t b=5;  // as you expected, this call the constructor of your object. 
        cout<<"hello"<<endl;
        b.print();  // as you could see, this call print() and print 5
        b=3;   // this is where the confusion begins. You didn't provide a way 
               // from your object to make an assigment from an integer, but you 
               // provide a way to construct an object from integer. So, your 
               // compiler will construct a temporary object, with 3 as parameter 
               // and use this object to do this assignment. Once this is a 
               // temporary object, it will be destructed at the end of this 
               // operation. That is why you are getting the message: 3   de
        b.print(); // print 3 as expected
        return 0;  // call the destruct from the object that was assigned before
      }
      

      【讨论】:

      • OP 询问为什么 t b=5;not 导致析构函数调用,因此行为并不完全“如您所料”。在这个非常简单的行中有令人讨厌的微妙之处:-)
      • 我猜,OP 在问为什么 t b=5 不调用析构函数,而 b=3 调用它。答案是因为t b=5是构造函数,而b=3是赋值。
      • 看我的回答。 t b=5; 需要一个复制构造函数,但复制构造可以被省略(而且通常是这样)。但是在非省略实现中,或者如果您在编译器上关闭复制省略,您看到复制和析构函数调用。
      猜你喜欢
      • 1970-01-01
      • 2020-05-14
      • 2016-09-12
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 1970-01-01
      • 2013-04-29
      • 2023-03-20
      相关资源
      最近更新 更多