конструктор, деструктор и временные копии

Я написал этот класс для проверки поведения конструктора по умолчанию, конструктора копирования, оператора присваивания и деструктора:

#include <iostream>

class Test {

public:
Test();

Test(const Test&);

~Test();

Test &operator=(const Test&);

private:
static int count;
int label;

};

Test::Test() : label(count++)
{
std::cout<<"constructor of "<<label<<std::endl;
}

Test::Test(const Test &other) : label(count++)
{
std::cout<<"copy-constructor of "<<label<<std::endl;
}

Test::~Test()
{
std::cout<<"destructor of "<<label<<std::endl;
}

Test &Test::operator=(const Test &other)
{
std::cout<<"copy assignment operator of "<<label<<std::endl;
}

int Test::count=0;

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

#include "Test.h"// argument passed and returned by reference
const Test &funct_by_ref(const Test &ref)
{
return ref;
}

// argument passed and returned by value
// call copy constructor to initialize parameter
Test funct_by_val(Test val)
{
// calls copy constructor to initialize temporary
return val;
}  // exits local scope,val is destroyed,calls val destructorint main()
{
// creates a temporary,calls 0 default constructor
Test();  // the temporary is destroyed at the end of the expression that created it
// calls 0 destructor
// creates a temporary (calls 1 default constructor) and calls 2 copy constructor
Test t2=Test(); // same as Test t2((Test()));
std::cout<<"--------------------------------"<<std::endl;
// calls 3 copy constructor
Test t3=t2;
// calls 4 default constructor
Test t4;
{
// calls 5 copy constructor
Test t5(t4);
} // local scope,t5 is destroyed,calls 5 destructor
// calls 4 assignment operator
t4=t2;
std::cout<<"-------------------------------"<<std::endl;
// nothing happens here
funct_by_ref(t4);
std::cout<<"-------------------------------"<<std::endl;
// calls copy constructor twice 6,7
funct_by_val(t4);
// temporary is destroyed at the end of the expression,calls destructor
}

но вместо этого я получаю следующий вывод:

constructor of 0
destructor of 0
constructor of 1
------------------------
copy-constructor of 2
constructor of 3
copy-constructor of 4
destructor of 4
copy assignment operator of 3
--------------------------
---------------------------
copy-constructor of 5
copy-constructor of 6
destructor of 6
destructor of 5
destructor of 3
destructor of 2
destructor of 1

все хорошо до первого ——————, где кажется, что создание объекта пропускается (я думаю о временном использовании для инициализации t2, потому что оно не уничтожается сразу после эта линия) и поэтому счет выключен на один ..

0

Решение

Test t2=Test(); // same as Test t2((Test()));

Здесь компилятор есть (и может) исключить копию и будет иметь такой же эффект, как и:

Test t2;
3

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

Стандарт имеет специальное положение, разрешающее — но не требующее — реализации исключать (т.е. не создавать) временные объекты, если единственный способ обнаружить их существование — это отслеживание вызовов конструктора и деструктора.

Различия, которые вы видите, заключаются в том, что ожидаемое вами поведение основано на создании и уничтожении временных объектов, и компилятор решает не создавать эти временные объекты. Обратите внимание, что решения об отмене временных показателей варьируются в зависимости от реализации (и часто зависят от настроек оптимизации).

0

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