Имеет ли std :: initializer_list конструктор копирования и используется ли он когда-либо? - PullRequest
2 голосов
/ 30 марта 2019

имеет ли std :: initializer_list конструктор копирования и, если он есть, используется ли он когда-либо и в каких случаях? потому что я заметил, что следующее не компилируется в GCC:

std::initializer_list<int>{{1,2,3,4}};

, в то время как нижеприведенный

class Test{
    public:
        Test(const std::initializer_list<int> &){}
};
Test{{1,2,3,4,5,6}};

Так что я подозреваю, что если бы std :: initializer_list имел конструктор, который есть в классе Test, первый фрагмент кода скомпилировал бы

Ответы [ 2 ]

5 голосов
/ 30 марта 2019

Так что я подозреваю, что если бы std :: initializer_list имел конструктор, который есть в классе Test, первый фрагмент кода скомпилировал бы

Это предполагает, что "равномерная инициализация" на самом деле равномерная , что всегда является опасным предположением.

initializer_list имеет особые правила построения из списка фигурных скобок. Если вы примените braced-init-list к initializer_list<T>, то включится [dcl.init.list] /3.5, который говорит идти «ниже», пропуская оставшиеся подпункты. А «внизу» говорит :

Объект типа std​::​initializer_­list<E> создается из списка инициализатора так, как если бы реализация генерировала и материализовала значение типа «массив из N const E», где N - количество элементов в инициализаторе. список.

Итак, вы создаете initializer_list<int> из одного элемента , который сам по себе является фигурным списком инициализации. Этот braced-init-list теперь применяется к E, то есть int. А поскольку в этом списке более одной записи, это не сработает.

Поскольку в подпункте 3.5 явно пропущены все остальные подпункты в этом разделе, не имеет значения , если этот внутренний фигурный список инициализации может создать initializer_list<int>. Компилятор никогда не проверяет это, потому что проверка для этого была в 3.6 , которая была пропущена.


Для записи, initializer_list имеет (по умолчанию) конструкторы копирования / перемещения и операторы присваивания.

1 голос
/ 30 марта 2019

Согласно cppreference , единственным доступным конструктором является конструктор по умолчанию.

Возможно, это связано с тем, как это обычно реализуется: стандартным массивом в стиле C. Для получения дополнительной информации я предложу это видео от Джейсона Тернера на CppCon2018 , которое дает представление о жизни.

Однако вы можете инициализировать контейнер с initializer_list, фактически рассматривая его как «копию».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...