Как конструктор копирования может быть вызван с помощью rvalue

MWE:

struct A {
    A() {std::cout << "constructor" << std::endl; }
    A(const A& a) {std::cout << "copy constructor" << std::endl; }
    A(A&& a) {std::cout << "move constructor" << std::endl; }
};

int main() {
    A a1{};
    A a2{ a1 };
    A a3{ A{} };
    A a4{ std::move(a3) };
    return 0;
}

Выход:

constructor
copy constructor
constructor
move constructor

заa2 Копирование elision используется, что является оптимизацией компилятора, и все вроде бы хорошо. Однако, когда я закомментирую конструктор перемещения, вместо конструктора перемещения вызывается конструктор копирования. Как можно преобразовать rvalue в ссылку const lvalue? Выход:

constructor
copy constructor
constructor
copy constructor

Программа составлена ​​в VS2017,

1 ответ

Решение

От en.cppreference.com:

Если предусмотрены конструкторы копирования и перемещения, а другие конструкторы не являются жизнеспособными, разрешение перегрузки выбирает конструктор перемещения, если аргумент является значением r того же типа (значением x, например, результатом std::move, или значением prvalue, например, безымянным. временный (до C++17)) и выбирает конструктор копирования, если аргумент является lvalue (именованный объект или функция / оператор, возвращающий ссылку на lvalue). Если предоставляется только конструктор копирования, все категории аргументов выбирают его (при условии, что он принимает ссылку на const, поскольку rvalues ​​может связываться с ссылками на const), что делает копирование запасного варианта для перемещения, когда перемещение недоступно.

Это ясно говорит о том, что rvalue может быть связано с константой lvalue.

Другие вопросы по тегам