C ++中的对象创建和销毁顺序 [英] Object creation and destruction order in C++

查看:264
本文介绍了C ++中的对象创建和销毁顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的程序,以了解有关C ++中创建和销毁对象的顺序的更多信息(使用Visual Studio 2015).在这里:

I wrote a simple program to learn more about the order of creating and destructing objects in C++ (using Visual Studio 2015). Here it is:

#include <iostream>
#include <string>

using namespace std;

class A
{
public:
    A(string name)
        : name(name)
    {
        cout << "A(" << name << ")::constructor()" << endl;
    }
    ~A()
    {
        cout << "A(" << name << ")::destructor()" << endl;
    }
private:
    string name;
};

class C
{
public:
    C(string name, A a)
        : name(name), a(a)
    {
        cout << "C(" << name << ")::constructor()" << endl;
    }
    ~C()
    {
        cout << "C(" << name << ")::destructor()" << endl;
    }
private:
    string name;
    A a;
};

class B
{
public:
    B(string name)
        : name(name)
    {
        cout << "B(" << name << ")::constructor()" << endl;
    }
    ~B()
    {
        cout << "B(" << name << ")::destructor()" << endl;
    }
private:
    string name;
    A a1{"a1"};
    A a2{"a2"};
    C c1{"c1", a1};
    A a3{"a3"};
};

int main()
{
    B b("b1");
    return 0;
}

输出使我有些惊讶(a1 s):

The output surprised me a little bit (the a1s):

A(a1)::constructor()
A(a2)::constructor()
C(c1)::constructor()
A(a1)::destructor()
A(a3)::constructor()
B(b1)::constructor()
B(b1)::destructor()
A(a3)::destructor()
C(c1)::destructor()
A(a1)::destructor()
A(a2)::destructor()
A(a1)::destructor()

要了解发生的事情的更多信息,我添加了有关对象实例的信息:

To learn more about what was going on I added information about the instances of objects:

    A(string name)
        : name(name)
    {
        cout << "A(" << name << ")::constructor(), this = " << this << endl;
    }
    ~A()
    {
        cout << "A(" << name << ")::destructor(), this = " << this << endl;
    }

结果更加令人惊讶:

A(a1)::constructor(), this = 0039FB28
A(a2)::constructor(), this = 0039FB44
C(c1)::constructor()
A(a1)::destructor(), this = 0039F8A8
A(a3)::constructor(), this = 0039FB98
B(b1)::constructor()
B(b1)::destructor()
A(a3)::destructor(), this = 0039FB98
C(c1)::destructor()
A(a1)::destructor(), this = 0039FB7C
A(a2)::destructor(), this = 0039FB44
A(a1)::destructor(), this = 0039FB28

也就是说,为什么a1的构造函数仅被称为一次而析构函数被称为 3次?我按值传递了a,因此显然至少创建了一个临时对象,但是请何时多少 A实例被创建并销毁?

Namely, why is a1's constructor only called once and destructor 3 times? I'm passing a by value so obviously at least 1 temporary object is created but please explain to me when and how many A instances are created and destroyed?

推荐答案

如注释中所述,当您将值作为参数传递给A类型的对象时,它们也会通过复制构造进行构造.为了看到这一点,您可以自己添加一个复制构造函数:

As already noted in the comments, objects of type A are also constructed via copy-construction when you pass them as arguments by value. In order to see this you can add a copy-constructor on your own:

A(const A& other)
: name(other.name)
{
    cout << "A(" << name << ")::copy-constructor(), this = " << this << endl;
}

示例输出:

A(a1)::constructor(), this = 0xbff3512c
A(a2)::constructor(), this = 0xbff35130
A(a1)::copy-constructor(), this = 0xbff350e8
A(a1)::copy-constructor(), this = 0xbff35138
C(c1)::constructor()
A(a1)::destructor(), this = 0xbff350e8
A(a3)::constructor(), this = 0xbff3513c
B(b1)::constructor()
B(b1)::destructor()
A(a3)::destructor(), this = 0xbff3513c
C(c1)::destructor()
A(a1)::destructor(), this = 0xbff35138
A(a2)::destructor(), this = 0xbff35130
A(a1)::destructor(), this = 0xbff3512c

在线试用

如您所见,当您将a1作为参数传递给c1的构造函数时,将发生一个复制构造,而当此构造函数初始化其成员a时,将发生第二个复制构造.此后,临时副本将在销毁后立即销毁,而在销毁c时销毁成员.

As you can see, one copy-construction happens when you pass a1 as parameter to the constructor of c1 and a second one happens when this constructor initializes its member a. The temporary copy is destructed immediately afterwards while the member is destructed when c is destructed.

修改:
此处,您可以在创建复制构造函数时阅读确切的规则.
为了不创建默认的复制构造函数,仅提供用户定义的构造函数是不够的,它必须是复制/移动构造函数.


Here you can read the exact rules when a copy-constructor is created.
In order to not create a default copy-constructor it is not sufficient to provide any user-defined constructor, it needs to be a copy/move-constructor.

源自C ++ 14标准(12.8复制和移动类对象):

Taken from C++14 standard (12.8 Copying and moving class objects):

7如果类定义未显式声明一个副本构造函数,则将隐式声明一个副本构造函数.如果类定义声明了move构造函数或move赋值运算符,则隐式声明的copy构造函数将定义为delete;否则,将其定义为默认值(8.4).如果该类具有用户声明的副本分配运算符或用户声明的析构函数,则不建议使用后一种情况.

7 If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

这篇关于C ++中的对象创建和销毁顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆