Skip to content

Instantly share code, notes, and snippets.

@NickTikhomirov
Last active June 20, 2019 11:36
Show Gist options
  • Save NickTikhomirov/ca9f35995f918b04fe1c3ce2f22ca5e0 to your computer and use it in GitHub Desktop.
Save NickTikhomirov/ca9f35995f918b04fe1c3ce2f22ca5e0 to your computer and use it in GitHub Desktop.
Конструктор, деструктор, конструктор копирования, конструктор перемещения

Вопроc 3, Конструктор, деструктор, конструктор копирования, конструктор перемещения

Автор: Никита

Головной раздел: Меню

Билет 3. Конструкторы и деструктор класса, конструктор копирования и конструктор перемещения, назначение, пример.

Конструктор - блок инструкций, вызываемый при создании объекта класса.

Деструктор - блок инструкций, вызываемый при уничтожении объекта класса.

Оба не имеют возвращаемых значений. Оба могут определяться как внутри класса, так и вне его

Назначение конструктора: присвоение каких-то значений полям, выделение памяти, открытие файлов и установление сетевых соединений.
Назначение деструктора: соответственно, наоборот очистка памяти и сохранение файлов.

Параметры конструктора. Конструктор может принимать какие-то значения в качестве аргументов - например, для установки значений полям. Также возможно создание нескольких конструкторов с разными параметрами. Деструктор всегда один и без параметров.

Оформление конструктора (внутри класса):

Имя_класса(Список_формальных_параметров){
  Операторы_тела конструктора
}

Оформление деструктора (внутри класса):

~Имя_класса(){
  Операторы_тела деструктора
}

Пример вызова конструктора:

  A *pA1 = new A;           //Без параметров, в куче
  A *pA2 = new A(42,69);    //С двумя параметрами, в куче
  A pA3();                  //С одним параметром
  A pA4 = 1;                //Такая формулировка возможна, если у класса есть конструктор с одним параметром. 
                            //В этом случае эта строчка идентична предыдущей.

Чтобы исключить вызов конструктора через присваивание, как показано в последнем примере, к конструктору дописывается ключевое слово explicit (перед конструктором).

Для конструктора, конструкторов копирования и перемещения, а также деструктора справедливо следующее: если программист не написал их сам, то компилятор допишет их за него. Такие конструкторы(деструкторы) называются неявными. Также важно понимать, что конструктор, декструтор, к.копирования и к.перемещения должны иметь доступ модификатор доступа public.

Конструктор копирования.

Это конструктор вида (для случая внутри класса):

A(const A& a){               //A - имя класса
  Операторы_тела конструктора
}

Он обязательно принимает в качестве аргумента ссылку на другой объект того же класса. Если программист пожелает, то конструктор может начать принимать что-то ещё.

Назначение конструктора копирования: копирование всех полей одного объекта в другой (по умолчанию). При переопределении может вытворять всё, что пожелает программист. Например, менять поля местами.

Благодаря этому конструктору, мы можем, например, писать вот так:

  A a1;
  A a2(a1);           //Конструктор копирования
  A a3=a1;            //Равносильно предыдущей строке

В данном примере для a2 и a3 будет вызван конструктор копирования, который скопирует каждое поле a1.

Самое главное про конструктор копирования: если вы оставили для полей-указателей простое копирование, то, когда в первом объекте (который мы копировали) они будут почищены (например, деструктором), во втором они также почистятся, а этого вы, скорее всего, не задумываете.

Если мы захотим сломать конструктор копирования, указав явно только один его вариант, который принимает не только ссылку, но и другие аргументы, то программа сама додумает за нас самый просто конструктор копирования с единственным аргументом (ссылкой). И пример, приведённый выше, всё ещё будет работать. А вот если мы сами напишем конструктор копирования с одним аргументом (ссылкой) и добавим к нему слово explicit, то пример работать перестанет, так как из-за третьей строчки программа не скомпилируется.

Также обратите внимание, что переопределив конструктор копирования вы никак не затронете обычные операции присваивания.

  A b;
  A a1 = b;          //Конструктор копирования (не explicit)
  A a2;              //Обычный конструктор
  a2 = b;            //Присваивание

Если мы переопределили конструктор копирования, чтобы он, например, менял местами поля и дописывал всякие нехорошие слова к полям-строкам, а затем запустили пример, приведённый выше, то эти действия произведутся только для a1, а объект a2 будет идентичен объекту b.

Конструктор перемещения.

Это конструктор вида (для случая внутри класса):

A(A&& a){               //A - имя класса
  Операторы_тела конструктора
}
Назначение конструктора перемещения: взять поля в исходном объекте и перекинуть в новый так, чтобы исходный можно было свободно уничтожить, не повредив новый. Пример реализации - скопировать поля в новый и занулить указатели в исходном, чтобы его деструктор не добрался до важных объектов.

Вызов конструктора перемещения в коде программы:

  A a1;
  A a2 = std::move(a1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment