【问题标题】:c++ function call the destructor immediately afterc ++函数在之后立即调用析构函数
【发布时间】:2018-06-03 12:01:56
【问题描述】:

在第一个 main 中,我们将调用复制构造函数来初始化两个对象 c 和 d。然后我们将在我的类中调用第一个 = 运算符,然后为这两个对象调用两次析构函数,输出为 I4I5c5d5d5

对于第二个main,我们调用默认构造函数,然后是5的构造函数的副本,然后我们在我的类中调用第二个运算符,在第二个运算符的末尾直接调用析构函数。

我不明白为什么在第一个 operator= 中使用该运算符后不调用析构函数,为什么在第二个 operator= 中使用第二个运算符后立即调用析构函数。

#include <iostream>

using namespace std;

class C {

  int i;

 public:


   C() : i(0)                  { cout << "D" << i; }

   C(int _i) : i(_i)           { cout << "I" << i; }

   C(const C& _c) : i(_c.i)    { cout << "C" << i;  }

   C& operator= ( const C& _c) { i = _c.i; cout << "c" << i; return *this; }

   C(C&& _c) : i(_c.i)         { cout << "M" << i; _c.i = 0; }

   C& operator= (C&& _c)       { i = _c.i; cout << "m" << i; _c.i = 0;
                                return *this; }

   ~C()                        { cout << "d" << i;  }
};


int main() {

  C c = 4;
  C d = 5;
  c = d;
}

/* int main() {
  C c;
  c = 5;
  } */

【问题讨论】:

  • 你说first main 和second main,这两个是什么意思? main 中的第一行和第二行代码还是 main 的两个不同版本?
  • 如果输出是I4I5c5d5d5,那么复制构造函数没有被调用。

标签: c++ c++11


【解决方案1】:

在c = 5; 行中没有任何赋值运算符采用int 可用,因此将创建一个临时的C(5),然后在赋值中使用。

这个临时的将在语句结束时被销毁。

【讨论】:

    【解决方案2】:

    第一版

    最后的析构函数调用与c = d;无关。

    调用它们是因为 c 和 d 超出范围并因此被销毁,所以让我们将它们从结果中删除,这给了我们:

    I4I5c5
    

    第一个I4和I5分别是由语句= 4和= 5构造的对象,它们是由接受int的构造函数创建的无名临时对象。

    但是等等,如果我们将c 和d 分配给临时人员,为什么不调用我们的C&amp; operator= (C&amp;&amp; _c)?

    那是因为复制省略。允许编译器完全消除这里的移动,即使它会产生副作用并且它只是在适当的位置构造对象。代码相当于:

    C a {4};
    C b {5};
    

    那么,最后一个c5就是因为c = d;。


    第二版

    对于第二个版本,这个省略是不允许的,因为我们不会立即构造对象.. C c = 5; vs C c; c = 5;。因此为 5 创建的临时对象调用移动赋值运算符,然后在运算符返回后立即销毁。

    【讨论】:

      猜你喜欢
      • 2014-09-18
      • 1970-01-01
      • 2012-02-10
      • 2016-03-02
      • 2021-07-19
      • 1970-01-01
      • 2011-07-10
      • 2021-03-04
      • 2021-03-30
      相关资源
      最近更新 更多