TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #1098 3.36K
​​Специальные методы классов
#новичкам

Помимо обычных методов, которые позволяют классу выполнить какую-то полезную работу, существуют методы, которые менеджерят самими объектами. Среди них выделяют так называемые "специальные" методы классов, которые компилятор неявно за вас сгенерирует. Давайте перечислим их и поясним, почему компилятор способен вообще для них написать код:

1️⃣ Конструктор по-умолчанию. Дефолтный конструктор без аргументов. Мы уже подробно разбирали его в предыдущих постах, останавливаться не будем.

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

2️⃣ Деструктор. Он семантически разрушает объект. Забирает у него память, закрывает дескрипторы и соединения, высасывает жизнь, отбирает квартиру, машину, жену и собаку и передает это государству операционной системе.

Как так получается, что компилятор вообще способен сам сгенерировать код деструктора объекта, который владеет ресурсами?

Все благодаря RAII и способности деструктора вызывать деструкторы своих полей. Если в вашем классе Foo содержится std::vector или std::unique_ptr, вам не нужно задумываться о менеджменте памяти, авторы этих классов уже все придумали за вас. Вам нужно лишь вызывать их деструктор, что деструктор Foo делает автоматически.

using File = std::unique_ptr<FILE, decltype(&std::fclose)>;

struct Foo {
std::vector<int> numbers;
File file;
// no explicit destructor ~Foo() {}
};

void foo() {
Foo obj = {{1, 2, 3, 4, 5, 6, 7, 8, 9}, {std::fopen("example.txt", "r"), &std::fclose}};
} // destroy obj here


3️⃣ Копирующий конструктор
4️⃣ Перемещающий конструктор

Для этой пары конструкторов правило единое: самое простое решение для копирования/перемещения объекта - это просто скопировать/переместить все его поля в другой объект. Компилятор с этим вполне справится сам: вызовет пачку нужных конструкторов да и все.

Естественно, если хотя бы у одного поля вашего класса не будет копирующего/перемещающего конструктора, сам ваш класс потеряет возможность копироваться/перемещаться.

struct Foo {
std::vector<int> numbers;
// no explicit copy/move constructors
// Foo(const Foo& other) {...}
// Foo(Foo&& other) {...}
};

void foo() {
Foo obj = {{1, 2, 3, 4, 5, 6, 7, 8, 9}};
Foo copied_in_obj = obj; // copy obj
Foo moved_in_obj = std::move(obj); // move from obj


5️⃣ Копирующий оператор присваивания
6️⃣ Перемещающий оператор присваивания

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

И вот здесь интересная комбинация.

Чтобы присвоить значение, нужно уметь разрушать текущее значение и передавать другое значение. То есть автоматическая генерация присваивания возможно благодаря тому, что компилятор сам умеет разрушать объект и копировать/присваивать значения полей.

Чуть остановимся на синтаксисе:

Foo a, b;
a = b; // copy assign
a = std::move(b); // move assign

Foo a1 = b; // THIS IS NOT AN ASSIGN


Последняя операция не является присваиванием - это вызов конструктора(в этом случае копирующего). Если объект только создается, то это всегда вызов конструктора.

Теперь примерчик:

struct Foo {
std::vector<int> numbers;
// no explicit copy/move constructors
// Foo& operator=(const Foo& other) {...}
// Foo& operator=(Foo&& other) {...}
};

void foo() {
Foo forward = {{1, 2, 3, 4, 5, 6, 7, 8, 9}};
Foo backward = {{9, 8, 7, 6, 5, 4, 3, 2, 1}};
Foo obj; // created obj here
obj = forward; // copy assign forward to obj
obj = std::move(backward); // move assign backward to obj


Итого: всего 6 специальных методов класса. Не больше, не меньше. На собесах любят про это спрашивать, так что забирайте.

Be special. Stay cool.

#cppcore #cpp11 #interview
  • 🔥 13
  • ❤ 8
  • 👍 7
More from @grokaemcpp
  1. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  2. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  3. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  4. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  5. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
  6. Sep 25, 2026​​std::spanstream #опытным Радостная весть для всех, кто пользуется iostreams! В C++23 доб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →