2014-01-18 2 views
0
#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    A() { cout << "A's constructor" << endl; } 
    ~A() { cout << "A's destructor" << endl; } 
}; 

class B 
{ 
public: 
    operator A() const { return A(); } 
}; 

void f(A q) {} 

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

Вот что я ожидал от кода, который должен был выполнить до того, как я его запустил: Вызов f приводит к вызову функции преобразователя в классе B, которая возвращает временный объект. Создается конструктор q, и когда f выходит, деструктор q вызывается. Я ожидал, что следующий вывод:Почему деструктор называется дважды?

конструктор в
деструктор A в

но выход я получил:

конструктор в
деструктор A в
деструктор A в

С есть еще один деструктор, должен быть создан дополнительный объект, поэтому mewhere. Может кто-нибудь объяснить, что здесь происходит?

+3

Поскольку вы делаете много копий-конструирования, вам также нужно отслеживать вызовы конструктора-копии. Почему ты этого не делаешь? Фактически, вы создаете так много копий, что наблюдение только двух объектов, несомненно, является следствием оптимизации. Технически вы должны иметь по крайней мере четыре, если не пять. – AnT

ответ

0

Вопрос был задан много раз раньше, но так как он настолько общий, что найти старшие сообщения сложно.

Вы передаете свои объекты вокруг по значению, а это означает, что копии создаются конструктор копирования. Конструктор копирования - это то, что создало этот «дополнительный объект» в вашем случае. Между тем вы ничего не выводите из конструктора копирования и поэтому не видите вызовы.

Вы также должны добавить вывод отладки в свой экземпляр-конструктор. Таким образом вы увидите, что на самом деле построено и когда.

+0

Я добавил конструктор копирования в класс a, как вы предлагали, и теперь один из вызовов деструктора не появляется на выходе. Странно то, что вывод из конструктора копирования тоже не отображается.Другими словами: когда я добавляю конструктор копирования, outpout становится: деструктором конструктора A, но текст, который я печатаю внутри конструктора копирования, не отображается. – Karlsson

0

Существует потенциал для создания 3 A объектов, построенных здесь. Сначала это временный объект, созданный A() в операторе преобразования. Тогда, поскольку возвращаемый тип оператора преобразования равен A, это временное копируется в возвращаемое значение. Затем возвращаемое значение преобразования копируется в параметр q из f.

Для копирования объекта вызывается конструктор копирования. Конструктор по умолчанию не будет вызываться, поэтому вы не увидите сообщение «конструктор», которое будет напечатано.

Как раз так бывает, что компилятор elides один из этих экземпляров, так что вы на самом деле имеете только одну копию. Какой из них уклоняется, я не могу сказать вам (но это, вероятно, копия в возвращаемое значение).

0

Я думаю, что первый вызов деструктора для временного объекта и второго деструктора для объекта, который построен семантикой перемещения.

0

Используйте это в качестве класса А:

class A 
{ 
public: 
    A() { cout << "A's constructor: " << this << endl; } 
    A(const A& a) { cout << "A's copy constructor: " <<this << " form " << &a << endl; } 
    A(A&& a) { cout << "A's move constructor: " <<this << " form " << &a << endl; } 
    A& operator=(const A& a) { cout << "A's assignment" <<this << " form " << &a << endl; } 
    ~A() { cout << "A's destructor: "<< this << endl; } 
}; 

И вы поймете, почему.

+0

Когда я запускаю свой код как есть, я получаю вывод: конструктор A: дескриптор 0018F8D4 A: 0018F8D4. Если я раскомментирую конструктор копирования из вашего кода, я получаю вывод: конструктор A: деструктор 002CFA5B A: деструктор 002CFA38 A: 002CFA5B – Karlsson

+0

@Karlsson: раскомментирование моего кода ??? Я не понимаю, что ты сделал –

Смежные вопросы