Структурируйте агрегатную инициализацию с меньшим количеством предложений, почему она все инициализирует?

Если у меня есть общая структура Linux, как:

struct sockaddr_in
{
sa_family_t    sin_family;
in_port_t      sin_port;
struct in_addr sin_addr;

unsigned char  __pad[__SOCK_SIZE__ - sizeof(short int)
- sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero        __pad

и я выполняю агрегатную инициализацию:

struct sockaddr_in my_addr = { 0 };

почему это инициализирует каждого члена в 0?

Я имею в виду: документация говорит:

Если количество предложений инициализатора меньше, чем количество
члены или инициализатор предложения полностью пустые, остальные
члены инициализируются их инициализаторами с фигурными или равными скобками, если
предоставляется в определении класса, а в противном случае (начиная с C ++ 14) пустым
списки, которые выполняют инициализацию значения.

чтобы было проще: почему этот код печатает 0?

struct sockaddr_in my_addr = {2, 2}; // initialize sin_family and sin_port to 2, everything else value-initialized

my_addr = {0};

std::cout << my_addr.sin_port; // Why is this 0?

3

Решение

Это покрыто в проект стандарта C ++ 14 раздел 8.5.4 Список инициализация который говорит:

Инициализация списка объекта или ссылки типа T определяется следующим образом:

и включает в себя:

Если T является агрегатом, выполняется агрегатная инициализация (8.5.1).

и имеет следующий пример:

struct S2 {
int m1;
double m2, m3;
}
S2 s21 = { 1, 2, 3.0 }; // OK
S2 s22 { 1.0, 2, 3 }; // error: narrowing
S2 s23 { }; // OK: default to 0,0,0

а также 8.5.1 сводные показатели который говорит:

Если в списке меньше инициализаторов, чем
члены в совокупности, затем каждый член
не явно инициализируется, должен быть инициализирован из его
инициализатор скобки или равный или, если нет
brace-or-equalinitializer, из пустого списка инициализаторов (8.5.4). [
Пример:

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };

инициализирует ss.a с 1, ss.b с «asdf», ss.c со значением
выражение вида int {} (то есть 0)

Обратите внимание, что 8.5.4 немного отличается в C ++ 11, он говорит:

Инициализация списка объекта или ссылки типа T определяется как
следующим образом:

  • Если список инициализаторов не имеет элементов и T является классом
    тип с конструктором по умолчанию, объект инициализируется значением.

  • В противном случае, если T является агрегатом, выполняется агрегатная инициализация
    (8.5.1).

2

Другие решения

почему это инициализирует каждого члена в 0?

Потому что это то, что C делает при инициализации структур, а C ++ делает то же самое для агрегатной инициализации для совместимости.

C делает это, потому что это более удобно (обычно это то, что вы хотите для членов, которым вы не даете явного значения) и безопаснее таким образом (это не оставляет опасно неинициализированные переменные, лежащие вокруг).

Если вы действительно хотите, чтобы другие члены структуры оставались неинициализированными, вы можете сделать это следующим образом:

struct sockaddr_in s; // entirely uninitialized
s.sin_family = 0;     // only initialize one member
1

По вопросам рекламы [email protected]