TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #1094 3.53K
Дефолтные конструкторы. Такие разные
#опытным

Существует 3 вида дефолтных конструкторов и важно понимать, в чем у них различия, чтобы разрешать нужную функциональность.

1️⃣ Тривиальный дефолтный конструктор

По сути задача дефолтного конструктора - вызывать у своих полей и подклассов дефолтный конструктор. А что если все поля класса имеют тривиальные типы?

struct Foo {
int i;
double d;
char c;
};


На самом деле у всех тривиальных базовых типов в С++ есть конструктор по-умолчанию. Но он тривиальный. То есть ничего вообще не делает и никак не инициализирует объект.

И это свойство может передастся конструктору Foo. Если для такого типа дефолтный конструктор будет сгенерирован компилятором, то он тоже ничего делать не будет.

Конструктор по-умолчанию называется тривиальным, если:

👉🏿 У класса нет виртуальных методов.
👉🏿 Все базы класса имеют тривиальные конструкторы по-умолчанию.
👉🏿 Все поля класса имеют тривиальные конструкторы по-умолчанию.

Все типы, которые совместимы с С, обладают этим свойством. Если вам нужна такая совместимость, тривиальный конструктор по-умолчанию - это ваш бро.

2️⃣ Нетривиальный дефолтный конструктор, сгенерированный компилятором

Если ваш класс содержит поле, у которого есть нетривиальный конструктор, то вам скорее всего и не нужна С-совместимость. Но вы можете приобрести кое-что другое.

Предоставив компилятору честь сгенерировать конструктор, вы разрешаете инициализировать объект с помощью агрегатной инициализации:

struct Foo {
// Foo() = default; так тоже можно
int i;
std::string s;
std::vector<int> v;
};

Foo f = {42, "Hello World", {1, 2, 3}};


можете даже designated initialization воспользоваться:

Foo f = {.i = 42, .s = "Hello World", .v = {1, 2, 3}};


Там есть конечно еще несколько требований, но опустим их, чтобы не сбивать фокус.

3️⃣ Нетривиальный пользовательский конструктор по-умолчанию

Как только вы сами определили дефолтный конструктор, то вы сразу же попали в эту категорию. И лишились преимуществ, описанных выше. Даже если вы определили пустой конструктор, он все равно считается кастомным:

struct Foo {
Foo() {};
int i;
std::string s;
std::vector<int> v;
};

Foo f = {42, "Hello World", {1, 2, 3}}; // ERROR



Да, с инициализацией у С++ довольно сложные отношения, но много чего идет от наследия С и обратной совместимости.

Don't be trivial. Stay cool.

#cppcore
  • 👍 17
  • ❤ 14
  • 🔥 6
  • ❤‍🔥 1
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 →