avatar
Грокаем C++
@grokaemcpp
24.06.2026 09:00
Дефолтные конструкторы. Такие разные
#опытным

Существует 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
11 16 3.3K

Обсуждение 11

Обсуждение не доступно в веб-версии. Чтобы написать комментарий, перейдите в приложение Telegram.

Обсудить в Telegram

Грокаем C++

9.3K
Два сеньора C++ - Владимир и Денис - отныне ваши гиды в этом дремучем мире плюсов.

По всем вопросам (+ реклама) @ninjatelegramm

Менеджер: @Spiral_Yuri
Реклама: https://telega.in/c/grokaemcpp
Мы на TGstat: https://tgstat.ru/channel/@grokaemcpp/stat
Открыть в Telegram