0 является пустым указателем константа
S.4.9:
Нулевой константный указатель является неотъемлемой константа (5.19) Rvalue целочисленного типа, который имеет значение нуль.
Нулевой константный указатель может быть преобразован в любой другой тип указателя:
S.4.9:
Нулевой константный указатель может быть преобразован в тип указателя; результат является нулевым значением указателя этого типа
Что вы дали для определения A
считаются совокупностью:
S.8.5.1:
Агрегатными представляет собой массив или класс без конструкторов, не объявленных пользователем, без частных или защищенных нестатических элементов данных, базовых классов и виртуальных функций.
Вы определяете положение об инициализации:
S.8.5.1:
Когда агрегат инициализируется инициализатор может содержать инициализатор-пункт, состоящий из скобки заключен, запятой списка из инициализатора-положений для членов совокупного
A
содержит член агрегата типа std::string
, и к нему применяется предложение инициализатора.
Ваш агрегат копия инициализируется
Когда агрегат содержит (будь то класс или массив) членов типа класса и инициализируется брекет прилагается инициализатора-лист, каждый такой элемент является копией -initialized.
Copy означает, что у вас есть эквивалент std::string s = 0
или std::string s = 42
инициализации;
S.8.5-12
Инициализация, что происходит в передачи аргументов, возврата функции, вызов исключения (15.1), обработка исключение (15.3), и скобки заключены-списки инициализатора (8.5 .1) называется копией-инициализацией и эквивалентна форме T x = a;
std::string s = 42
не компилируется, потому что нет неявного преобразования, std::string s = 0
компилируется (поскольку неявное преобразование существует), но приводит к неопределенному поведению.
std::string
«s конструктор 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;
}
Шаблон класса 'boost :: array' также является агрегатом. Таким образом, вы можете использовать 'array a = {" foo "," bar "};' с ним, например. Кроме того, мой lazy-construct-array также является агрегатом: http://stackoverflow.com/questions/2662417/c-suppress-automatic-initialization-and-destruction/2662526#2662526 –
Неявные преобразования + агрегаты ... ಠ_ಠ –
@litb, когда я впервые увидел эту особенность «boost :: array», у меня было просветление, сексуальное удовлетворение от ААА. Простые вещи, которые имеют такой смысл, имеют тенденцию делать это со мной. – wilhelmtell