Порядок создания и уничтожения объектов в переполнении стека

Я написал простую программу, чтобы узнать больше о порядке создания и уничтожения объектов в C ++ (с использованием Visual Studio 2015). Вот:

#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;
}

Результат меня немного удивил ( 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()

Чтобы узнать больше о том, что происходит, я добавил информацию об экземплярах объектов:

    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конструктор только называется один раз и деструктор три раза? Я прохожу a По значению, очевидно, создается хотя бы 1 временный объект, но, пожалуйста, объясните мне когда а также Как много A экземпляры созданы и уничтожены?

1

Решение

Как уже отмечалось в комментариях, объекты типа A также создаются посредством конструкции копирования, когда вы передаете их в качестве аргументов по значению. Чтобы увидеть это, вы можете добавить конструктор копирования самостоятельно:

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.

Редактировать:
Вот Вы можете прочитать точные правила при создании конструктора копирования.
Чтобы не создавать конструктор копирования по умолчанию, недостаточно предоставить какой-либо определяемый пользователем конструктор, он должен быть конструктором копирования / перемещения.

Edit2:

Взято из стандарта C ++ 14 (12.8 Копирование и перемещение объектов класса):

7 Если определение класса не объявляет явно конструктор копирования, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолтный (8.4). Последний случай считается устаревшим, если в классе есть объявленный пользователем оператор копирования или объявленный пользователем деструктор.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]