#c
#c
Вопрос:
Когда массив был инициализирован объектами anonymus, деструктор отображает допустимые значения, но я создаю массив с объектами, конструктор переопределения копирования не вызывается, а также деструктор отображает значения мусора.
Я пытался понять это, отображая значения, но все еще запутался.
class Check{
private:
int a;
public:
Check()
{
this->a = 9999;
cout << "n Default Constructor Called n";
}
Check(int i)
{
this->a = i;
}
Check(const Check amp; obj)
{
cout << "COPY CONSTRUCTORn";
}
~Check()
{
cout << this->a<<" DESTRUCTOR n";
}
};
Check b[2] = {Check(5),Check(4)};
Check obj1(2);
Check obj2(3);
Check a[2] = {obj1,obj2};
Я ожидал вывода «КОНСТРУКТОРА КОПИРОВАНИЯ» 4 раза, но это было только два раза и никаких мусорных значений. Фактический результат показан ниже:
COPY CONSTRUCTOR COPY CONSTRUCTOR 32649 DESTRUCTOR -1330935392 DESTRUCTOR 3 DESTRUCTOR 2 DESTRUCTOR 4 DESTRUCTOR 5 DESTRUCTOR
Комментарии:
1. Значения мусора связаны с тем, что в конструкторе копирования вы не инициализируете
this->a
2. @M.M можете ли вы сказать мне, почему конструктор копирования вызывается только 2 раза?
3. Выведите значение
a
в каждом конструкторе, и вы поймете, почему.4. @EtiennedeMartel почему в этом случае не вызывается конструктор копирования:Проверьте b[2] = {Проверка(5),Проверка(4)};»
5. @usamamw141 это называется устранением копирования . Объекты создаются непосредственно там и никогда не копируются
Ответ №1:
Причина в том, что не выполняется копирование.
В этом случае:
Check b[2] = {Check(5),Check(4)};
Поскольку оба значения являются временными, компилятору разрешено (или, в C 17, принудительно) оптимизировать копирование и вместо этого создавать объекты на месте.
Однако во втором случае:
Check a[2] = {obj1,obj2};
obj1
и obj2
не являются временными, поэтому в этом случае должны иметь место реальные копии.
Ответ №2:
В:
Check b[2] = {Check(5),Check(4)};
этот синтаксис означает, что аргументами конструктора для двух элементов массива являются 5
и 4
. Это не означает, что аргументы являются временными.
Check(5)
является выражением prvalue, это не обязательно означает, что материализуется временное значение. Один из способов, которым prvalue может быть «использовано», — это инициализатор для объекта того же типа.
Это поведение изменилось в C 17; до этого концептуально всегда существовало временное, но временное могло быть опущено по усмотрению компилятора.