C++:定义多个构造函数时的对象创建/销毁序列

C++: Object creation/destruction sequence when multiple constructors are defined

本文关键字:创建 对象 定义 构造函数 C++      更新时间:2023-10-16

运行以下简单代码 (C++11(

#include <iostream>
using namespace std;
class test {
public:
  int par;
  test(int par_) : par(par_) {
    cout << "constructor (par = " << par << " )" << endl;
  }
  test( int par_, char dummy) {
    test( (int)par_ );
  }
  test() { test(100); }

  // Copy constructor
  test(const test& x) { cout << "copy constructor (par = " << x.par << " )" << endl; }
  // Move constructor
  test(test&& x) { cout << "move constructor (par = " << x.par << " )" << endl; }
  // Copy assignemnt
  test& operator=(const test& x) { cout << "copy assignemnt (par = " << x.par << " )" << endl;  return *this; }
  // Move assignement
  test& operator=(test&& x) { cout << "move assignemnt (par = " << x.par << " )" << endl; return *this; }

  ~test() { cout << "destructor (par was " << par << " )" << endl; }
};

/****************************************************************************/
int main() {
  cout << "=========================" << endl;
  test tst_2(10, 0);
  cout << "=========================" << endl;
  test tst_1(5);
  cout << "=========================" << endl;
  test tst_0;
  cout << "=========================" << endl;
  cout << tst_2.par << " " << tst_1.par << " " << tst_0.par << endl;
  return 0;
}

我得到输出

=========================
constructor (par = 10 )
destructor (par was 10 )
=========================
constructor (par = 5 )
=========================
constructor (par = 100 )
destructor (par was 100 )
=========================
-858993460 5 -858993460
destructor (par was -858993460 )
destructor (par was 5 )
destructor (par was -858993460 )

实际上,tst_2和tst_0的对象会立即被摧毁......并在行刑结束时再次被摧毁!

但是,如果我将构造函数部分替换为以下内容

:
  test(int par_) : par(par_) {
    cout << "constructor 1 param (par = " << par << " )" << endl;
  }
  test( int par_, char dummy) : par(par_) {
    cout << "constructor 2 params (par = " << par << " )" << endl;
  }
  test()  : par(100) {
    cout << "constructor 0 params (par = " << par << " )" << endl;
  }
:

行为正是我所期望的:

=========================
constructor 2 params (par = 10 )
=========================
constructor 1 param (par = 5 )
=========================
constructor 0 params (par = 100 )
=========================
10 5 100
destructor (par was 100 )
destructor (par was 5 )
destructor (par was 10 )

问题是:为什么第一个实现在创建后立即销毁对象(构造函数调用另一个对象(?

test( int par_, char dummy)
{
    test( (int)par_ ); // secret is here!
}

标记的行处,您将在堆栈上创建另一个对象,就在构造器内,该对象在构造函数离开后再次销毁。如果你想做构造函数转发(从C++11开始尽可能(,你必须这样做:

test( int par_, char dummy) : test(par_)
{ }

在默认构造函数 ( test(100); ( 中都一样。

您在两个构造函数中从构造函数的主体内部调用test。因此,在构造函数中调用test是一个具有本地作用域的对象。一旦程序执行离开其中一个构造函数,您的本地范围test就会被销毁,从而调用析构函数。