Ответ 1
Если вы не определяете эти четыре метода (шесть в С++ 11), компилятор будет генерировать их для вас:
- Конструктор по умолчанию
- Конструктор копирования
- Оператор присваивания
- Destructor
- Переместить конструктор (С++ 11)
- Назначение перемещения (С++ 11)
Если вы хотите узнать, почему? Он должен поддерживать обратную совместимость с C (потому что C-структуры можно копировать с использованием = и в декларации). Но это также упрощает упрощение написания простых классов. Некоторые утверждают, что это добавляет проблемы из-за проблемы "мелкой копии". Мой аргумент против этого состоит в том, что у вас не должно быть класса с имеющимися в нем RAW-указателями. Используя соответствующие интеллектуальные указатели, проблема исчезнет.
Конструктор по умолчанию (если не определены другие конструкторы)
Созданный компилятором конструктор по умолчанию вызовет конструктор по умолчанию базовых классов, а затем каждый конструктор по умолчанию каждого члена (в том порядке, в котором они объявлены)
Деструктор (если не определено деструктор)
Вызывает деструктор каждого члена в обратном порядке объявления. Затем вызывает деструктор базового класса.
Копировать конструктор (если конструктор копирования не задан)
Вызывает конструктор копии базового класса, передающий объект src. Затем вызывает конструктор копирования каждого члена, используя члены объектов src в качестве значения, которое нужно скопировать.
Оператор присваивания
Вызывает оператор присваивания базового класса, передающий объект src. Затем вызывает оператор присваивания для каждого члена, используя объект src в качестве значения, которое нужно скопировать.
Переместить конструктор (если конструктор перемещения не задан)
Вызывает конструктор перемещения базового класса, передающий объект src. Затем вызывает конструктор перемещения каждого элемента, используя члены объектов src, в качестве значения, которое нужно переместить.
Оператор назначения переноса
Вызывает оператор присваивания базового класса, передающий объект src. Затем вызывает оператор присваивания перемещения для каждого члена, используя объект src в качестве значения, которое нужно скопировать.
Если вы определяете класс следующим образом:
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
};
Что создаст компилятор:
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
// Conceptually two different versions of the default constructor are built
// One is for value-initialization the other for zero-initialization
// The one used depends on how the object is declared.
// some_struct* a = new some_struct; // value-initialized
// some_struct* b = new some_struct(); // zero-initialized
// some_struct c; // value-initialized
// some_struct d = some_struct(); // zero-initialized
// Note: Just because there are conceptually two constructors does not mean
// there are actually two built.
// value-initialize version
some_struct()
: some_base() // value-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it
// PODS not initialized
, str2()
{}
// zero-initialize version
some_struct()
: some_base() // zero-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it.
, a(0)
, b(0)
, c(0) // 0 is NULL
, str2()
// Initialize all padding to zero
{}
some_struct(some_struct const& copy)
: some_base(copy)
, str1(copy.str1)
, a(copy.a)
, b(copy.b)
, c(copy.c)
, str2(copy.str2)
{}
some_struct& operator=(some_struct const& copy)
{
some_base::operator=(copy);
str1 = copy.str1;
a = copy.a;
b = copy.b;
c = copy.c;
str2 = copy.str2;
return *this;
}
~some_struct()
{}
// Note the below is pseudo code
// Also note member destruction happens after user code.
// In the compiler generated version the user code is empty
: ~str2()
// PODs don't have destructor
, ~str1()
, ~some_base();
// End of destructor here.
// In C++11 we also have Move constructor and move assignment.
some_struct(some_struct&& copy)
// ^^^^ Notice the double &&
: some_base(std::move(copy))
, str1(std::move(copy.str1))
, a(std::move(copy.a))
, b(std::move(copy.b))
, c(std::move(copy.c))
, str2(std::move(copy.str2))
{}
some_struct& operator=(some_struct&& copy)
// ^^^^ Notice the double &&
{
some_base::operator=(std::move(copy));
str1 = std::move(copy.str1);
a = std::move(copy.a);
b = std::move(copy.b);
c = std::move(copy.c);
str2 = std::move(copy.str2);
return *this;
}
};