Если у меня есть общая структура 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?
Это покрыто в проект стандарта 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).
почему это инициализирует каждого члена в 0?
Потому что это то, что C делает при инициализации структур, а C ++ делает то же самое для агрегатной инициализации для совместимости.
C делает это, потому что это более удобно (обычно это то, что вы хотите для членов, которым вы не даете явного значения) и безопаснее таким образом (это не оставляет опасно неинициализированные переменные, лежащие вокруг).
Если вы действительно хотите, чтобы другие члены структуры оставались неинициализированными, вы можете сделать это следующим образом:
struct sockaddr_in s; // entirely uninitialized
s.sin_family = 0; // only initialize one member