Страницы

Поиск по вопросам

среда, 4 марта 2020 г.

Uniform initialization

#cpp #cpp11


В С++11 появился новый синтаксис инициализации. Вот что по этому поводу пишет Скотт
Майерс в книге Effective Modern C++:

class Widget {
public:
  Widget();                                   // default ctor
  Widget(std::initializer_list il);      // std::initializer_list ctor
  …                                           // no implicit conversion funcs
}; 

Widget w1;          // calls default ctor
Widget w2{};        // also calls default ctor
Widget w3();        // most vexing parse! declares a function!    

Widget w4({});      // calls std::initializer_list ctor with empty list
Widget w5{{}};      // ditto  


Если взять его пример, выкинуть лишнее, и добавить печать в конструктор Widget, то
окажется что Widget w4({}); и Widget w5{{}}; это не одно и то же:

#include 
#include 

class Widget{
public:
    Widget(){

    }
    Widget(std::initializer_list l){
        std::cout << "l.size = " << l.size() << std::endl;
    }
};

int main(){
    Widget w4({}); //l.size = 0
    Widget w5{{}}; //l.size = 1
}


Пример

У меня два вопроса:


Скотт нас обманывает?
Что происходит на самом деле? 

    


Ответы

Ответ 1



Widget(std::initializer_list l)//Это initializer-list constructor Следуя стандарту, он имеет приоритет над другими конструкторами в list-initialization. Initializer-list constructors are favored over other constructors in list-initialization (16.3.1.7) Widget w4({}); Это direct-initialization. Инициализатор - пустой std::initializer_list. Widget w4{{}}; Это уже list-initialization. В данном случае direct-list-initialization. Если список инициализации пуст, то выбирается конструктор по-умолчанию. Если же список инициализации не пуст, то конструктор выбирается в две фазы: Initially, the candidate functions are the initializer-list constructors (11.6.4) of the class T and the argument list consists of the initializer list as a single argument If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list. Начинаем первую фазу "ручного" поиска подходящего конструктора. В первой фазе все аргументы рассматриваются как один initializer list. Если рассмотреть скобочки в инициализаторе как создание std::initializer_list, то можно ли создать std::initializer_list, передав ему {}? Да, можно std::initializer_list{{/*вот он наш единственный int со значением 0*/}}` Всё, подходящий конструктор найден. То есть в нашем случае Widget w5{{}}; //приведет к такому --> Widget w5(std::initializer_list{int{}}); Или еще примеры: Widget w5{{1}, {2}};//--> Widget w6(std::initializer_list{int{1}, int{2}}); Widget w7{{1, 2}};//--> Widget w8(std::initializer_list{std::initializer_list{1, 2}}); Старался объяснить как можно проще, поэтому, изложение "своими словами" может быть не совсем точным.

Комментариев нет:

Отправить комментарий