Почему вызов 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
.
Ответы
Ответ 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));
}