Почему мой деструктор, как представляется, вызывается чаще, чем конструктор?

#include<iostream>
using namespace std;

class A{
public:
    static int cnt;
    A()
    { 
        ++cnt; 
        cout<<"constructor:"<<cnt<<endl;
    }
    ~A()
    {
        --cnt;
        cout<<"destructor:"<<cnt<<endl;
    }
};

int A::cnt = 0;

A f(A x){
    return x;
}
int main(){
    A a0;
    A a1 = f(a0);
    return 0;
}

Программа выведет:

constructor:1
destructor:0
destructor:-1
destructor:-2

Конструктор и деструктор не отображаются попарно?

Ответ 1

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

A(const A&)
{ 
    ++cnt; 
    cout<<"copy constructor:"<<cnt<<endl;
}

Если вы не добавляете его явно, компилятор генерирует тот, который ничего не делает с счетчиком cnt.

Это выражение

A a1 = f(a0);

создает копии a0, которые используют конструктор копирования. Точное количество копий может варьироваться в зависимости от copy elision, но ваш cnt должен быть 0 в конце программы.

Примечание. В С++ 11 вы также должны рассмотреть возможность создания компилятора созданного конструктора перемещения, однако, как только вы объявите свой собственный конструктор копирования, компилятор больше не генерирует версию перемещения.

Ответ 2

Вы не отслеживаете конструкторы all, а только конструктор по умолчанию. Компилятор сгенерировал конструктор копирования и использовал его несколько раз, учитывая два объекта, которые перечислены как уничтоженные, а не созданные.

Ответ 3

Вам нужно также посчитать вызовы конструктора копирования. В С++ 11 есть также конструкторы перемещения, которые необходимо учитывать.