Подтвердить что ты не робот

Почему вызов std:: move на объект const вызывает конструктор копирования при передаче другому объекту?

Почему вызов std:: move на объект const вызывает конструктор копирования при передаче другому объекту? В частности, код

#include <iostream>

struct Foo {
    Foo() = default;
    Foo(Foo && x) { std::cout << "Move" << std::endl; }
    Foo(Foo const & x) = delete;
};

int main() {
    Foo const x; Foo y(std::move(x)); 
}

не удается скомпилировать сообщение:

g++ -std=c++14 test07.cpp -o test07
test07.cpp: In function 'int main()':
test07.cpp:10:36: error: use of deleted function 'Foo::Foo(const Foo&)'
     Foo const x; Foo y(std::move(x)); 
                                    ^
test07.cpp:6:5: note: declared here
     Foo(Foo const & x) = delete;
     ^
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1

Конечно, я ожидаю, что он потерпит неудачу, потому что мы не можем переместить значение const. В то же время я не понимаю маршрут, который выполняет код, прежде чем он попытается вызвать конструктор копирования. Смысл, я знаю, что std::move преобразует элемент в значение x, но я не знаю, как все происходит после этого по отношению к const.

4b9b3361

Ответ 1

Тип результата вызова std::move с аргументом T const - T const&&, который не может привязываться к параметру T&&. Следующее лучшее совпадение - это ваш конструктор копирования, который удален, следовательно, ошибка.

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

Результат имеет смысл, потому что конструкция перемещения - это операция, которая крадет ресурсы из исходного объекта, тем самым изменяя его, поэтому вы не сможете сделать это с объектом const, просто позвонив std::move.

Ответ 2

Тип std::move(x) - Foo const&&, который не может привязываться к Foo&&. Обоснование такое же, как и для T const& невозможности привязки к T&. Однако вы можете создать конструктор с Foo const&&. Скорее всего, вы не сможете реально перемещать соответствующие данные объекта, но, например, в вашем примере нет данных, т.е. Следующий код работает нормально:

#include <iostream>

struct Foo {
    Foo() = default;
    Foo(Foo &&) { std::cout << "Move\n"; }
    Foo(Foo const&&) { std::cout << "Move const\n"; }
    Foo(Foo const &) = delete;
};

int main() {
    Foo const x; Foo y(std::move(x)); 
}