2013-08-12 5 views
19
struct SS {int a; int s;}; 

int main() 
{ 
    vector<SS> v; 
    v.push_back(SS{1, 2}); 
} 

Код может быть скомпилирован без каких-либо ошибок. Однако, когда структура инициализируется в классе, я получил ошибку компиляции. Может ли кто-нибудь объяснить это?C++ 11 ошибка инициализации структуры проекта

struct SS {int a = 0; int s = 2;}; 

Ошибка:

In function ‘int main()’: 
error: no matching function for call to ‘SS::SS(<brace-enclosed initializer list>)’ 
    v.push_back(SS{1, 2}); 
         ^
note: candidates are: 
note: constexpr SS::SS() 
struct SS {int a = 0; int s = 2;}; 
     ^
note: candidate expects 0 arguments, 2 provided 
note: constexpr SS::SS(const SS&) 
note: candidate expects 1 argument, 2 provided 
note: constexpr SS::SS(SS&&) 
note: candidate expects 1 argument, 2 provided 

ответ

28

В C++ 11, когда вы использовать не инициализации статического члена данных в момент декларации, как вы делаете здесь:

struct SS {int a = 0; int s = 2;}; 

вы делаете класс a неагрегат. Это означает, что вы больше не можете инициализировать экземпляр так:

SS s{1,2}; 

Чтобы сделать этот синтаксис инициализации работу для не-заполнителя, вы должны добавить конструктор двухпараметрического:

struct SS 
{ 
    SS(int a, int s) : a(a), s(s) {} 
    int a = 0; 
    int s = 2; 
}; 

Это ограничение было отменено на C++ 14.

Обратите внимание, что вы можете добавить конструктор по умолчанию для класса. Наличие созданного пользователем конструктора запрещает генерируемый по умолчанию компилятор.

См. Соответствующую информацию here.

+3

Правильно, я собирался ответить аналогичным образом. Это можно увидеть и без возможностей C++ 11, добавив пользовательский конструктор 'SS() {}'. – hvd

+4

C++ 14 больше не будет исключать классы с инициализаторами в классе из агрегатов; См. Http: // www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html – bames53

+1

@ bames53 Спасибо, я этого не знал. Это отличная новость. Я считаю это правило чрезмерно ограничительным. – juanchopanza

4

Использование инициализатора члена по умолчанию делает класс/STRUCT с неагрегированным:

§ 8.5.1 агрегатами

Агрегат представляет собой массив или класс (пункт 9) нет конструкторов, предоставляемых пользователем (12.1), Отсутствие логических или равных инициализаторов для нестатических членов данных (9.2), без частных или защищенных нестатических данных (раздел 11), без базовых классов (раздел 10) , и нет виртуальных функций (10.3).

Семантика отличаются для агрегатов и не совокупностей:

заполнители (например, массивов и структур):

Initialize members/elements beginning-to-end. 

Non-заполнители:

Invoke a constructor. 

v.push_back(SS{1, 2}); // Error, it tries to call SS constructor 

что означает вам нужен конструктор сейчас:

struct SS 
{ 
    SS(int a, int s) : a(a), s(s) 
    { 
    } 
    int a = 0; 
    int s = 2; 
}; 
+0

Интересно, что это больше не верно в C++ 1y, агрегированным членам разрешено иметь скобки или равные-intializers. N3690 §8.5.1/7 говорит об инициализации агрегатов из списков с биполярными init-списками: «Если в списке меньше элементов-инициализаторов *, чем в агрегате есть члены, то каждый член , явно не инициализированный, должен быть инициализирован из его * brace-or-equal-initializer * или, если нет * скобки-равного-инициализатора *, из пустого списка инициализаторов (8.5.4). " – Casey

-7

struct SS {int a = 0, int s = 2;};

обмена с запятой в запятой, может быть i'am просто

+0

даже сама структура не будет компилироваться – RiaD

+0

Нет, это не отвечает на вопрос. – soon

Смежные вопросы