简体   繁体   中英

Why does calling std::move on a const object call the copy constructor when passed to another object?

Why does calling std::move on a const object call the copy constructor when passed to another object? Specifically, the code

#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)); 
}

fails to compile with the message:

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

Certainly, I expect it to fail because we can't move a const value. At the same time, I don't understand the route that the code takes before it tries to call the copy constructor. Meaning, I know that std::move converts the element to an x-value, but I don't know how things proceed after that with respect to const .

The type of the result of calling std::move with a T const argument is T const&& , which cannot bind to a T&& parameter. The next best match is your copy constructor, which is deleted, hence the error.

Explicitly delete ing a function doesn't mean it is not available for overload resolution, but that if it is indeed the most viable candidate selected by overload resolution, then it's a compiler error.

The result makes sense because a move construction is an operation that steals resources from the source object, thus mutating it, so you shouldn't be able to do that to a const object simply by calling std::move .

The type of std::move(x) is Foo const&& which can't bind to Foo&& . The reasoning is the same as for a T const& not being able to bind to a T& . You can, however, have a constructor taking a Foo const&& . Most likely you won't be able to really move the corresponding object's data but, eg, in your example there no data, ie, the following code works OK:

#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)); 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM