什么时候自动调用析构函数?

时间:2017-06-09 11:16:52

标签: c++

我正在玩destructoroperetor=,输出对我来说很奇怪。

两个版本的主要功能:

int main()
{
    B b1;
    B b2;
    b2=b1;
    cout<<"---"<<endl;
    return 0;
}
  1. 以下代码按预期工作,输出为:
  2. class B { public: B operator=(B& b1) { cout<<"operator="<<endl; return b1; } ~B() { cout<<"destructor"<<endl; } }; 输出:

    operator=
    destructor // Did it print because `b2` got new value so the old value is going to trash?
    --
    destructor
    destructor
    
    1. 现在operator = return B&而不是B,输出不一样;析构函数被调用两次而不是之前的三次。为什么?
    2. class B { public: B& operator=(B& b1) { cout<<"operator="<<endl; return b1; } ~B() { cout<<"destructor"<<endl; } }; 输出:

      operator=
      --
      destructor
      destructor
      

2 个答案:

答案 0 :(得分:2)

在第一种情况下,您还有一个额外的实例:

int main()
{
    B b1;
    B b2;
    b2=b1;               <---- here b2.operator=(b1) returns another B instance 
                               (its a copy of b1)
    cout<<"---"<<endl;
    return 0;
}

在行尾已被破坏,因为你没有保留对它的引用。你可以写:

   B b3 = (b2=b1); 

使实例保持活动状态直到范围结束。在这种情况下,您会看到在打印---后调用析构函数。

另请注意,在操作符应将*this的引用返回给其他实例的情况下,两个运算符都不正确。 (在PaulMcKenzie的评论中已经提到过,只需在此重复一遍以确保它不会丢失)

答案 1 :(得分:0)

代码工作正常并且符合预期。在第一种情况下,析构函数在&#34; operator =&#34;之后被调用。因为您要返回B对象的本地副本:

B operator=(B& b1)
{
    cout<<"operator="<<endl;
    return b1;
}

请注意声明&#34;返回b1&#34;将返回本地副本(而不是引用),并且一旦作用域结束它将被破坏。您可以通过编写自己的复制构造函数来测试验证这一点,并在其中添加一条跟踪。我做了以下事情:

class B
{
    public:
        B operator=(B& b1)
        {
            cout<<"operator="<<endl;
            return b1;
        }
        ~B()
        {
            cout<<"destructor"<<endl;
        }

        B(const B& b1){
            cout << "Copy constructor called" << endl;   
        }

        B(){}
};

我得到了以下输出:

operator=
Copy constructor called
destructor
---
destructor
destructor

然而,在赋值运算符重载的返回类型为B&amp;的第二种情况下,永远不会调用复制构造函数,因为它将返回对它接收的对象的引用,而不是副本。因此,对于在main()方法中创建的对象b1和b2,析构函数只会被调用两次。 希望这能解答您的疑问。