Performing some operation on std::move(x)

Let's get the formalities out of the way.

17.3.28 valid but unspecified state [defns.valid]

an object state that is not specified except that the object's invariants are met and operations on the object behave as specified for its type

[ Example: If an object x of type std::vector<int> is in a valid but unspecified state, x.empty() can be called unconditionally, and x.front() can be called only if x.empty() returns false. — end example ]

Some users have suggested that std::move(x).something() is nonsensical. But I'm having trouble understanding the difference between std::move(x).something() and y = std::move(x); y.something(). Observe:

// -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
std::vector<int> v;
v.pop_back();
// Error: attempt to access an element in an empty container.

Now we want to try our nonsensical case:

std::vector<int> v(10);
std::move(v).pop_back();

No error. This must be the "valid but unspecified" everyone's talking about, but let's keep going.

std::vector<int> v(10);
std::cout << std::move(v).size();
auto v2 = std::move(v);
std::cout << v.size();

This prints 100. That's not too surprising. std::move is just a cast, it doesn't actually perform the job of the move constructor.

Am I missing something or is std::move(x).something() still non-sensical (other than being a no-op)?


For reference, see the comments on Member function .begin() and std::begin() as well as the upvoted answer.

The following example suggests that v is not moved from:

template< class C >
auto begin( C&& c ) -> decltype(c.begin())
{
    return c.begin();
}

int main()
{
    std::vector<int> v(10);
    std::vector<int>::iterator it3 = begin(std::move(v));
    std::cout << v.size();
}

Outputs 10.

Upvotes: 2

Views: 84

Answers (2)

SergeyA
SergeyA

Reputation: 62583

std::move doesn't do anything to the object! All it does is casting an object to an ravlue, so that it can be bound by rvalue reference.

Any modifications to the object are done by corresponding move constructor or move assingnment operator. If none are called, nothing happens at all.

Upvotes: 5

Jarod42
Jarod42

Reputation: 217275

But I'm having trouble understanding the difference between std::move(x).something() and y = std::move(x); y.something()

With (note the &/&& after const)

struct S
{
    void foo() const & {std::cout << "l-value this\n"; }
    void foo() const && {std::cout << "r-value this\n"; }
};

You got:

S tmp;
std::move(tmp).foo(); // "r-value this

S x = std::move(tmp);
x.foo(); // "l-value this

Upvotes: 0

Related Questions