Почему элементы std :: initializer_list должны быть скопированы? - PullRequest
2 голосов
/ 26 марта 2020

cppreference говорит:

Базовым массивом является временный массив типа const T [N], в котором каждый элемент инициализируется копией (за исключением того, что сужающие преобразования недействительно) из соответствующего элемента исходного списка инициализатора. Время жизни базового массива такое же, как и у любого другого временного объекта, за исключением того, что инициализация объекта initializer_list из массива продлевает время жизни массива точно так же, как привязка ссылки к временному объекту (с теми же исключениями, например, для инициализации не -stati c ученик). Базовый массив может быть размещен в постоянной памяти.

В чем причина этого решения? Почему перемещение не в порядке?

А как насчет copy-ellision?

struct A { A(const A&){ std::cout << "Oh no, a copy!\n"; } };
struct B { B(std::initializer_list<A> il); };

int main()
{
    B b{ A{} };
    return 0;
}

Мой компилятор удаляет копию. Но гарантированно ли уничтожены эти копии?

1 Ответ

1 голос
/ 26 марта 2020

«Копировать инициализацию» в C ++ не означает, что вещи обязательно будут скопированы. Это просто формальное имя для ограничений, при которых будет происходить инициализация. Например, при инициализации копирования явные c 'кандидаты не являются кандидатами. Таким образом, следующий код будет неправильно сформирован

#include <iostream>
#include <initializer_list>

struct A {
    explicit A() = default;
    A(const A&){ std::cout << "Oh no, a copy!\n"; } 
};
struct B { B(std::initializer_list<A> il); };

int main()
{
    B b{ {} };
    return 0;
}

Единственный элемент в списке должен инициализироваться копией из {}, что влечет за собой вызов по умолчанию c ' тор. Однако, поскольку c 'отмечен явно, эта инициализация не может произойти.

Исключение копирования, безусловно, возможно до C ++ 17 и обязательно в C ++ 17 и выше в определенных контекстах. В вашем примере под компилятором C ++ 17, поскольку вы предоставляете инициализатор, который является prvalue (чистое значение, а не объект), правила инициализации C ++ требуют, чтобы цель инициализировалась напрямую , без промежуточных объектов. Несмотря на то, что контекст называется «инициализация копирования», лишних объектов нет.

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