堆栈上的构造函数/析构函数调用顺序

时间:2013-04-21 09:53:24

标签: c++ constructor destructor assignment-operator

我有以下简单的代码:

class A
{
    int a;
public:
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; }
    ~A()            { cout << "Destructor  a=" << a << endl; }
    void print()    { cout << "Print       a=" << a << endl; }
};

void f()
{
    A a(1);
    a.print();
    a = A(2);
    a.print();
}

int main()
{
    f();
    return 0;
}

输出结果为:

Constructor a=1
Print       a=1
Constructor a=2
Destructor  a=2
Print       a=2
Destructor  a=2

我发现有两个析构函数调用a=2而没有a=1,而每个案例都有一个构造函数调用。那么在这种情况下如何调用构造函数和析构函数?

5 个答案:

答案 0 :(得分:7)

a = A(2);

将使用默认operator=a分配新值,将其a::a成员值设置为2。

void f()
{
    A a(1);//a created with int constructor a.a == 1
    a.print();// print with a.a == 1
    a = A(2);//Another A created with int constructor setting a.a == 2 and immediately assigning that object to a
    //object created with A(2) deleted printing 2 it was created with
    a.print();//a.a==2 after assign
}//a deleted printing 2 it was assigned with

您可能应该阅读Rule of three以更好地了解正在发生的事情。

答案 1 :(得分:4)

void f()
{
    A a(1);
      //  Constructor a=1
    a.print();
      //  Print       a=1
    a = A(2);
      // Constructor a=2
      // also operator=
      // Destructor  a=2
    a.print();
      // Print       a=2
      // Destructor  a=2
}

答案 2 :(得分:2)

这是因为您没有销毁A(1)您为其分配A(2),让我们通过添加assign operator扩展您的示例:

class A
{
    int a;
public:
    A(int a) : a(a) { cout << "Constructor a=" << a << endl; }
    ~A()            { cout << "Destructor  a=" << a << endl; }
    void print()    { cout << "Print       a=" << a << endl; }
    A &operator=(const A &other) {
        cout << "Assign operator old=" << a << " a=" << other.a << endl; 
        a = other.a;
    }
};

这将导致:

[vyktor@grepfruit tmp]$ ./a.out 
Constructor a=1
Print       a=1
Constructor a=2
Assign operator old=1 a=2 <- This line explains why destructor is not called
Destructor  a=2
Print       a=2
Destructor  a=2

如果你有其中一个实施:

  • 析构函数 - 销毁所有对象的成员
  • 复制构造函数 - 从复制构造函数参数中的等效成员构造所有对象的成员
  • 复制赋值运算符 - 从赋值运算符参数中的等效成员分配所有对象的成员

你应该实现所有这些。这称为rule of three

答案 3 :(得分:2)

void f()
{
    A a(1); // Constructor a=1 (a.a(1) is called)
    a.print(); // Print a=1
    a = A(2); // Constructor a=2 (Temporary unnamed object A(2) is constructed)
              // compiler generated a.operator=(const A&); is called and then
              // Destructor  a=2 (Temporary unnamed object is destroyed.
    a.print(); // Print a=2
              // Destructor  a=2 (a.~a() is called)
}

答案 4 :(得分:1)

首先调用a = 1的构造函数

其次,打印称为

第三个你创建的新对象A(2)的构造函数叫做。

第四,将此对象分配给对象a对象a = 2

的数据成员

第五个对象A(2)的析构函数叫做

第六个对象a的析构函数叫做