Как использовать унифицированный синтаксис C ++ 11? - PullRequest
13 голосов
/ 30 сентября 2011

Я не могу понять, когда и как использовать новый унифицированный синтаксис инициализации в C ++ 11.
Например, я получаю это:

std::string a{"hello world"}; // OK
std::string b{a};  // NOT OK

Почему это не работает во втором случае? Ошибка:

error: no matching function for call to ‘std::basic_string<char>::basic_string(<brace enclosed initializer list>)’    

с этой версией g ++ g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2.

А с примитивными данными какой синтаксис мне следует использовать?

int i = 5;
int i{5};
int i = {5};

Ответы [ 3 ]

20 голосов
/ 30 сентября 2011

Ошибка компиляции для

// T t{u};
std::string a;
std::string b{a};

Сочетание четырех вещей

  • В проекте до недавнего времени говорилось, что если T имеет конструктор списка инициализаторов (std::string имеет один, принимая char элементов), то список инициализаторов передается сам в качестве аргумента. Таким образом, аргументом для конструктора (ов) является не a, а {a}.

  • В проекте говорится, что список инициализатора, инициализирующий ссылку, создается не путем прямой привязки, а путем создания временного элемента вне списка в списке инициализатора, а затем привязки целевой ссылки к этому временному объекту.

  • В проекте говорится, что при инициализации ссылки списком инициализаторов, когда инициализация ссылки не является прямой привязкой, эта последовательность преобразования является определяемой пользователем последовательностью преобразования.

  • В проекте говорится, что при передаче самого списка инициализатора при рассмотрении конструкторов класса X в качестве кандидатов в сценарии разрешения перегрузки в контексте, подобном описанному выше, затем при рассмотрении первого параметра конструктора типа "ссылка на cv X "(cv = const / volatile) - другими словами, весьма вероятно, что это конструктор копирования или перемещения, тогда никакие определенные пользователем преобразования не допускаются. В противном случае, если такое преобразование будет разрешено, вы всегда можете работать с неопределенностью, поскольку при инициализации списка вы не ограничены только одним вложенным определением, определенным пользователем.

Сочетание всего вышеперечисленного состоит в том, что нельзя использовать конструктор для взятия {a}. Тот, кто использует initializer_list<char>, не совпадает, а другие, использующие string&& и const string&, запрещены, потому что они потребуют определенных пользователем преобразований для привязки их параметра к {a}.

.

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

10 голосов
/ 30 сентября 2011

Первый пример должен работать, вызывая конструктор копирования. Если вы используете GCC, это было исправлено в 4.6.

В последних примерах есть небольшая нестилистическая разница.

int i = 5.0;   // fine, stores 5
int i{5.0};    // won't compile!
int i = {5.0}; // won't compile!

Разница в том, что единый синтаксис инициализации не позволяет сужать преобразования. Вы можете принять это во внимание при выборе между ними.

4 голосов
/ 30 сентября 2011

Это не работает, потому что вы забыли точку с запятой:

std::string b{a};
               ^^^

В противном случае этот синтаксис нормален и вызывает конструктор копирования.

Для второго вопроса используйте int i{5}; если вы хотите быть единообразным, хотя int i = 5;, вероятно, более читабельно.

...