Инициализация структуры с помощью агрегатной инициализации и инициализаторов элементов [duplicate]

этот вопрос уже есть ответ здесь:

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

#include <iostream>
#include <string>
struct ABC
{
    std::string str;
    unsigned int id ;/* = 0 : error: no matching constructor for initialization of 'ABC'*/
};

int main()
{
    ABC abc{"hi", 0};
    std::cout << abc.str << " " << abc.id <<   std::endl;
    return 0;
}

при определении структуры ABC без значения по умолчанию для id clang 3.x и gcc 4.8.х скомпилировать код без проблемы. Однако после добавления аргумента по умолчанию для " id " я получаю сообщение об ошибке:

13 : error: no matching constructor for initialization of 'ABC'
ABC abc{"hi", 0};
^ ~~~~~~~~~
4 : note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
struct ABC
^
4 : note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
4 : note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided
1 error generated.
Compilation failed

С технической точки зрения, что происходит, когда я определяю id с аргументом по умолчанию и почему в этом случае инициализация aggregate невозможна? Я неявно определяю какой-то конструктор?

2 ответов


Бьярне Страуструп и Ричард Смит подняли вопрос о совокупной инициализации и инициализаторах-членах, не работающих вместе.

определение aggregate немного изменено в стандарте C++11 & C++14.

из C++11 Стандарт Проект n3337 в разделе 8.5.1 говорится, что:

агрегат-это массив или класс (пункт 9) без предоставления пользователем конструкторы (12.1), нет бандаж или равно инициализатор для нестатического data members (9.2), не private или protected нестатических членов данных (Пункт 11), без базовых классов (пункт 10) и без виртуальных функций (10.3).

но c++14 стандартных проектов n3797 в разделе 8.5.1 говорится, что:

агрегат-это массив или класс (пункт 9) без предоставления пользователем конструкторы (12.1), не private или protected нестатических членов данных (Пункт 11), без базовых классов (пункт 10), и никаких виртуальных функций (10.3).

Итак, когда вы используете в инициализаторе члена класса (т. е. равный инициализатора) для элемента данных id в C++11 он больше не остается агрегированным , и вы не можете написать ABC abc{"hi", 0}; инициализации struct ABC. потому что после этого он больше не остается агрегатным типом. Но ваш код действителен в C++14. (См. live demo здесь).


в C++ структура и классы одинаковы, за исключением того, что структуры имеют открытые члены по умолчанию,а классы-частные. Если вы хотите использовать начальные значения, я думаю, вам нужно написать конструктор или использовать что-то вроде этого:

struct ABC
{
    std::string str;
    unsigned int id;
} ABC_default = {"init", 0 }; //initial values

int main()
{
    ABC abc = ABC_default;
    std::cout << abc.str << " " << abc.id << std::endl;
    return 0;
}