Когда конструктор C++ не вызывается?
У меня есть ситуация, когда ни один конструктор не вызывается:
#include <iostream>
using namespace std;
int main ()
{
class yoyo
{
public:
int i;
yoyo()
{
i = 0;
cout << "defaultly initialized to 0" << endl;
}
yoyo (int j) : i(j)
{
cout << "initialized to " << j << endl;
}
};
int i;
yoyo a;
cout << "Hello1, i: " << a.i << endl;
yoyo b(5);
cout << "Hello2, i: " << b.i << endl;
yoyo c = b; /* 1 */
cout << "Hello3, i: " << c.i << endl;
return 0;
}
Выход:
defaultly initialized to 0
Hello1, i: 0
initialized to 5
Hello2, i: 5
Hello3, i: 5
(Примечание: между Hello2 и Hello3 ничего нет)
Если я изменю программу следующим образом:
#include <iostream>
using namespace std;
int main ()
{
class yoyo
{
public:
int i;
yoyo()
{
i = 0;
cout << "defaultly initialized to 0" << endl;
}
yoyo (int j) : i(j)
{
cout << "initialized to " << j << endl;
}
};
int i;
yoyo a;
cout << "Hello1, i: " << a.i << endl;
yoyo b(5);
cout << "Hello2, i: " << b.i << endl;
yoyo c; c = b; /* 1 */
cout << "Hello3, i: " << c.i << endl;
return 0;
}
(Единственная разница в том, что строка помечена /* 1 */)
Результат теперь:
defaultly initialized to 0
Hello1, i: 0
initialized to 5
Hello2, i: 5
defaultly initialized to 0
Hello3, i: 5
Теперь есть вызов конструктора между Hello2 и Hello3. Мой вопрос, почему нет (видимого) вызова конструктора в первом случае?
4 ответа
В случае
yoyo c = b;
это конструктор копирования, который вызывается.
И в случае
yoyo c; c = b;
это оператор присваивания копии, который вызывается.
Если вы не предоставите ни одного из них, компилятор сгенерирует версии по умолчанию для вас.
Если вы хотите создать свой собственный конструктор копирования, он может выглядеть так:
yoyo(const yoyo& other)
: i(other.i)
{ std::cout << "copy constructor initialized\n"; }
Оператор присваивания копии выглядит так:
yoyo& operator=(const yoyo& other)
{
i = other.i;
return *this;
}
Оба они определены внутри определения класса, конечно.
В первом случае:
yoyo c = b;
вызывает copy constructor
, который компилятор генерирует для вас неявно в этом случае.
yoyo c = b;
Это называется копией-инициализацией; сгенерированный компилятором конструктор копирования будет вызван и c
будет инициализирован с этой копией. Кроме того, конструктор по умолчанию c
будет называться.
c = b;
Здесь это не инициализация, это присваивание. Сгенерированный компилятором оператор присваивания будет вызван в этой строке.
В вашем коде,
yoyo c=b
вызовет copy constructor.Если вы хотите, чтобы он вызывался, вы должны определить его явно.
например:
yoyo(const yoyo& obj)
{
this->i=obj.i; cout<<"copy constructor"<<endl;
}
во втором случае он будет вызывать конструктор, а затем оператор присваивания
yoyo c; //constructor
c = b; //assignment operator for which only copying occurs
Вы можете перегрузить оператор присваивания, как показано ниже
yoyo& operator=(yoyo& obj)
{
i = obj.i;
cout << "assignment operator" << endl;
}