Подтвердить что ты не робот

Как использовать синтаксис синтаксиса С++ 11?

Я не могу понять, когда и как использовать новый унифицированный синтаксис инициализации в С++ 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};
4b9b3361

Ответ 1

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

// 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}.

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

Ответ 2

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

Последние примеры имеют небольшую не стилистическую разницу.

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

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

Ответ 3

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

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

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

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