C ++ 11 — C ++ (11): когда использовать прямую или копировать инициализацию, если оба в порядке

До того, как начнутся крики о дублировании: я знаю, что следующий вопрос (и некоторые другие) довольно с этим связан:

Есть ли разница в C ++ между инициализацией копирования и прямой инициализацией?

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

Рассмотрим код:

A createA(){...}

A a1 = createA();
A a2(createA());

Предположим, что A может быть неявно сконструирован с помощью копирования и тому подобного, поэтому обе инициализации a1 а также a2 в порядке. Там нет никаких побочных эффектов в конструкторе копирования для Aпоэтому обе инициализации также семантически эквивалентны. createA() возвращает непосредственно тип переменной, а не что-то еще, что должно быть приведено первым. Я думаю, что этот случай довольно распространен.

Итак, в этом случае, где обе альтернативы одинаково применимы и семантически эквивалентны, какой из них мне следует использовать? Есть ли рекомендация в спецификации или консенсус / лучшая практика в сообществе, или это только от меня и моего стиля кодирования, какой использовать? Введены ли в C ++ 11 какие-либо различия по сравнению со старыми стандартами?

3

Решение

Нет всегда лучшего ответа, это вопрос стиля.

При инициализации объекта из простого выражения типа объекта (например, createA()) Я часто использую copy-init, вероятно, просто из-за знакомства с = Форма назначения. В противном случае, когда инициализатор другого типа или имеется несколько инициализаторов для объекта (например, несколько аргументов конструктора или агрегатный init), я предпочитаю использовать C ++ 11 list-initialization (так называемый унифицированный синтаксис инициализации), который можно использовать в больше мест, например инициализировать агрегаты, а также классы с помощью пользовательских конструкторов, и не может быть проанализирован как объявление функции:

A a1{ createA() };

Приведенная выше форма list-init использует direct-init, тогда как эта форма использует copy-init:

A a2 = { createA() };

При использовании list-init я предпочитаю форму direct-init без избыточности = знак.

Есть несколько случаев, когда list-init невозможен, например, когда тип имеет конструктор списка инициализатора (то есть тот, который принимает параметр, который является специализацией std::initializer_list) и вы хотите вызвать другой конструктор, но будет выбран конструктор списка инициализатора, например, std::vector<int> v{ 5u, 0 }; не будет создавать вектор из пяти элементов со значением ноль, но вектор с двумя элементами со значениями пять и ноль

1

Другие решения

Если все остальное одинаково (семантика, производительность, …), это, очевидно, только вопрос вкуса и / или стиля. Однако в наши дни многие авторы рекомендуют инициализировать список для прямой инициализации:

A a3 {createA()};

Но я бы сказал, что вам решать (если это ваш забавный проект) или вашим коллегам выбрать одну из двух (трех) альтернатив. я мог бы не Рекомендуем использовать оба взаимозаменяемо, потому что это заставит читателей задуматься, почему вы используете иногда прямую, а иногда копируемую инициализацию

2

По вопросам рекламы [email protected]