Инициализация списка и удаление копии

Рассмотрим следующий пример:

#include <cstdlib>
struct A
{
A(int, char*){};
A(const A&){ printf("copy-ctor\n"); }
};
int main()
{
A x = A(5, nullptr);
}

Согласно 8.5.16 (стандарта C ++ 11) строка

    A x = A(5, nullptr);

рассматривается как

    A x(A(5, nullptr));

(то есть временный объект типа A создается и передается copy-ctor типа A для инициализации x). Тогда согласно 12.8.31 допускается компилятор (но не принудительно) выполнить оптимизацию под названием «исключение копирования», чтобы исключить создание временного типа A, который эффективно превращает эту строку кода в

    A x(5, nullptr);

(т. е. не создаются временные файлы, не называются копи-ctors).

Теперь предположим, что я использую инициализацию списка в приведенном выше примере следующим образом:

    A x = {5, nullptr}; // (1)

или же

    A x = A{5, nullptr}; // (2)

Может кто-нибудь, пожалуйста процитировать соответствующие фараграфы из стандарта C ++ 11 которые подтверждают или опровергают, что (1) и / или (2) всегда (то есть, не только когда компилятор может выполнить оптимизацию «copy elision»), должен рассматриваться как

    A x(5, nullptr);

(то есть первый конструктор A вызывается напрямую, временные файлы не создаются, копирование объектов типа A не выполняется).

3

Решение

Этот ответ, по-видимому, неверен, что удивило меня, чтобы узнать. Смотрите комментарии. Я думаю, что первая и четвертая маркированные точки в [dcl.init.list] / 3 — это то, что означает (1), вызывает конструктор (или выполняет агрегатную инициализацию) напрямую, без временной.

В стандарте нет ничего, что гарантировало бы, что (1) и (2) избегают временного. Они оба являются инициализацией копирования, (1) инициализацией списка копирования, как определено в [dcl.init.list] p1:

Инициализация списка может происходить в контексте прямой инициализации или инициализации копирования; инициализация списка в контексте прямой инициализации называется прямой список инициализация и инициализация списка в контексте инициализации копирования называется копирование списка инициализация.

В обоих случаях это инициализация копирования, и [dcl.init] говорит, что это может включать перемещение (которое может быть исключено).

8.5/14,15:

Инициализация, которая происходит в форме

T x = a;

[…] называется copy-initialization.

Инициализация, которая происходит в формах

T x(a);

T x{a};

[…] называется прямой инициализацией.

Если ваш компилятор не достаточно умен, чтобы всегда исключать временное, то для обеспечения отсутствия временного с инициализацией списка вы можете использовать прямую инициализацию списка, т.е.

A x{5, nullptr};
3

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

Других решений пока нет …