Я знаю, что здесь довольно много ответов на эту тему, но я не смог найти тот, который полностью ответил на мой вопрос.
Ниже я делаю некоторые предположения, основанные на моем понимании инициализации (какC ++ 17). Было бы хорошо, если бы кто-то мог указать / исправить мои ошибки.
Учитывая тип
struct A
{
int x;
};
, создание локальной переменной вообще не инициализирует объект
A a; // a.x is indeterminate, accessing it is UB
Однако мы можем принудительно инициализировать агрегат с помощью следующего
A a{};
A a = {};
, который инициализирует a.x
в 0
.
Теперь, учитывая тип
struct B
{
int x;
std::string s;
};
при создании локальной переменной default инициализируется объект
B b;
, в результате чего b.s
инициализируется по умолчанию (потому что это не POD), но b.x
неопределен, доступ к нему по-прежнему UB.
Далее у нас есть
struct C
{
int x = 0;
std::string s;
};
. Создание локальной переменной по умолчанию инициализирует объект
C c;
, что приводит к инициализации C.s
по умолчанию (потому что это неPOD) и c.x
при инициализации копирования, поведение хорошо определено.
Наконец, давайте сравним некоторые типы и проверим, имеют ли они идентичное поведение инициализации. Я предполагаю, что нет никакой разницы между этими типами, если я создаю (инициализированную по умолчанию) локальную переменную (A a;
).
Случай A
struct A1
{
int x;
};
struct A2
{
A2() { }
int x;
};
struct A3
{
A3() = default;
int x;
};
x
никогда не инициализируется, это значение не определено.
Случай B
struct B1
{
int x{};
};
struct B2
{
B2() : x{} { }
int x;
};
struct B3
{
B3() = default;
int x = 0;
};
x
всегда инициализируется, его значение равно 0
.
Дело C
struct C1
{
int x;
std::string s;
};
struct C2
{
C2() { }
int x;
std::string s;
};
struct C3
{
C3() = default;
int x;
std::string s;
};
s
всегда инициализируется по умолчанию, но x
никогда не инициализируется, его значение не определено.
Являются ли эти утверждения правильными, а если нет, то где ошибки и каково реальное поведение?