Когда имеет смысл заменить & quot; имя_класса obj_name = func () & quot; от & quot; имя_класса obj_name {func ()} & quot ;?

В коде я вижу следующую конструкцию:

const class_name obj_name{func()};

func () возвращает объект класса с именем class_name, Итак, мне интересно, почему бы не использовать следующую конструкцию:

const class_name obj_name = func();

5

Решение

const class_name obj_name{func()};

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

Учти это,

struct X { /*....*/ }; // some class

struct Y
{
Y();
Y(int i);
Y(X x);
};

Теперь можно написать это:

Y y(100); // declare an object y of type Y

это вызывает второй конструктор, что нормально. Пока все хорошо!

Но случайно один даже написать это:

Y y();

(ошибочно) думая, что он вызывает конструктор по умолчанию. Но дело в том, что он не вызывает конструктор по умолчанию. Вместо этого он объявляет функцию y который не принимает аргументов и возвращает Y, Это называется досадный разбор в C ++.

Точно так же можно написать это (случайно),

Y y(X());

думая, что он вызывает третий конструктор, передавая объект типа X который создается на лету. Опять же, это неправильно. Вместо этого он объявляет функцию y который берет указатель на функцию (типа функция, которая ничего не берет и возвращает X) и вернуться Y, Это называется самый неприятный разбор в C ++.

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

Y y1{};      // invokes 1st constructor
Y y2{100};   // invokes 2nd constructor
Y y3{X{}};   // invokes 3rd constructor

и следуя тому же синтаксису,

Y { function_call() };

const class_name obj_name { func() }; // taken from your question!

То есть единообразный и, конечно, лучшая практика, не так ли?

Надеюсь, это поможет.

5

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

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

В этом случае оба синтаксиса будут вызывать class_name(class_name const&) конструктор копирования (если таковой существует). Поэтому нет никакой разницы. Это просто вопрос предпочтений.

Следует отметить, что {} синтаксис не всегда ведет себя как в этом случае: если есть конструктор initialization_list соответствующего типа, этот конструктор используется, иначе элементы класса инициализируются с использованием соответствующего конструктора.

В случаях, когда Most Vexing Parse принцип (если он может быть интерпретирован как прототип функции, то так и будет) поражает вас тем, что вы должны использовать любой из двух, чтобы сообщить компилятору, что следующее не является прототипом функции:

typename class_name obj_name(func());
class_name obj_name { func() };
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector