0 - константа нулевого указателя
S.4.9:
Константа нулевого указателя - это целочисленное константное выражение (5.19) r целого типа, которое оценивается как
нуль.
Константа нулевого указателя может быть преобразована в любой другой тип указателя:
S.4.9:
константа нулевого указателя может быть преобразована в тип указателя; результатом является значение нулевого указателя этого
тип
То, что вы дали для определения A
, считается совокупным:
S.8.5.1:
Агрегат - это массив или класс без объявленных пользователем конструкторов, без приватных или защищенных
нестатические члены-данные, без базовых классов и виртуальных функций.
Вы указываете предложение инициализатора:
S.8.5.1:
Когда агрегат инициализируется, инициализатор может содержать предложение инициализатора, состоящее из закрытой скобки,
разделенный запятыми список пунктов инициализатора для элементов совокупности
A
содержит элемент агрегата типа std::string
, и к нему применяется условие инициализатора.
Ваш агрегат инициализируется копией
Когда агрегат (класс или массив) содержит члены типа класса и инициализируется закрытой скобкой
список инициализаторов, каждый такой элемент инициализируется копией.
Копирование инициализации означает, что у вас есть эквивалент std::string s = 0
или std::string s = 42
;
S.8.5-12
Инициализация, которая происходит при передаче аргумента, возврате функции, выдаче исключения (15.1), обработке
исключение (15.3), и заключенные в скобки списки инициализаторов (8.5.1) называются инициализацией копирования и эквивалентны
в форме Т х = а;
std::string s = 42
не скомпилируется, поскольку неявное преобразование отсутствует, std::string s = 0
скомпилируется (поскольку неявное преобразование существует), но приводит к неопределенному поведению.
Конструктор std::string
для const char*
не определен как explicit
, что означает, что вы можете сделать это: std::string s = 0
Просто чтобы показать, что вещи на самом деле инициализируются копией, вы можете сделать этот простой тест:
class mystring
{
public:
explicit mystring(const char* p){}
};
struct A {
mystring s;
};
int main()
{
//Won't compile because no implicit conversion exists from const char*
//But simply take off explicit above and everything compiles fine.
A a = {0};
return 0;
}