В коде я вижу следующую конструкцию:
const class_name obj_name{func()};
func () возвращает объект класса с именем class_name
, Итак, мне интересно, почему бы не использовать следующую конструкцию:
const class_name obj_name = func();
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!
То есть единообразный и, конечно, лучшая практика, не так ли?
Надеюсь, это поможет.
Начиная с C ++ 11 равномерная инициализация была введена функция, которая предоставляет несколько способов инициализации типов.
В этом случае оба синтаксиса будут вызывать class_name(class_name const&)
конструктор копирования (если таковой существует). Поэтому нет никакой разницы. Это просто вопрос предпочтений.
Следует отметить, что {}
синтаксис не всегда ведет себя как в этом случае: если есть конструктор initialization_list соответствующего типа, этот конструктор используется, иначе элементы класса инициализируются с использованием соответствующего конструктора.
В случаях, когда Most Vexing Parse принцип (если он может быть интерпретирован как прототип функции, то так и будет) поражает вас тем, что вы должны использовать любой из двух, чтобы сообщить компилятору, что следующее не является прототипом функции:
typename class_name obj_name(func());
class_name obj_name { func() };