Копирующая инициализация

class A {
    int _x;
public:
    A(int x) : _x(x) {}

};

int main()
{
    A s = 2; // вот она
}

Я не понимаю как это работает? Так как копирующая инициализация инициализирует объект из другого объекта, компилятор видит литерал int и приводит к типу A, то есть в теории должен вызваться конструктор для создания анонимного объекта, что бы потом вызвать конструктор копирования и инициализировать объект s анонимным объектом? Получается что это будет выглядеть так: A s = A(2);?

На практике компилятор это все оптимизирует будет вызван один конструктор. Получается если ход мыслей верный, то по этой причине копирующая инициализация носит такое название?


Ответы (1 шт):

Автор решения: HolyBlackCat

должен вызваться конструктор для создания анонимного объекта, что бы потом вызвать конструктор копирования

До С++17 так и происходит. И непонятно, почему стандарт не требует вызывать сразу правильный конструктор, без копирования.

Но:

  • Тут перемещение, а не копирование.
  • Не A s = A(2);, а A s(A(2));. Это проверяется деланием перемещающего (или копирующего, если перемещающего нет) конструктора explicit.
  • Любой нормальный компилятор соптимизирует перемещение. От него остается только требование наличия перемещающего (или копирующего) конструктора, но и это требование исчезает в С++17.
  • Начиная С++17, все это неважно, потому что компилятор обязан выбросить перемещение, не проверяя наличие перемещающего (или копирующего) конструктора. Поэтому A s = 2; превращается просто в A s(2);, с единственной разницей, что конструктор от int-а не может быть explicit.
→ Ссылка