Во-первых: объекты b.a.a
, b.a.b
, b.a.c
, b.a.d
гарантированно инициализированы нулем. Что для float
инициализируется, как если бы = 0;
(не обязательно представление всех нулевых битов).
B b{};
переводится в нулевую инициализацию только в некоторых случаях (страница cppreference немного вводит в заблуждение ).
В C ++ 14: Поскольку B
является агрегатом , это агрегатная инициализация, каждый член инициализируется как будто пустым списком. Итак, A a;
инициализируется, как если бы A a{};
. A
также является агрегатом, поэтому каждый из его элементов инициализируется как будто пустым списком, который для встроенных типов имеет нулевую инициализацию.
В C ++ 11 формулировка была другой (список инициализация агрегированного класса из пустого списка фактически не считалась агрегатной инициализацией), но результат был таким же.
В C ++ 03, B b{}
; была синтаксическая ошибка, но B b = {};
было разрешено, а также, оказывается, инициализировать нулем рассматриваемые числа с плавающей запятой.
В C ++ 98 правила были другими, и, короче говоря, B b = {};
будет вызывать конструктор по умолчанию A
, который оставляет значения неинициализированными. Нам нравится притворяться, что инициализации C ++ 98 никогда не существовало, но некоторые компиляторы придерживались этих правил даже в 2010-е годы.
* 1030 инициализированное число с плавающей запятой гарантированно действует как
false
для оператора
||
, см.
Сравнение числа с плавающей запятой с нулем .
Стандарт гласит: «Нулевое значение, значение нулевого указателя или значение нулевого указателя на член преобразуется в false
». Что не на 100% точно, но ИМО инициализированный нулем float
должен считаться для этой цели «нулевым значением».