GuLearn
GuLearn

Reputation: 1864

Can I std::move() an element out of a std::vector?

I have a std::vector<std::string> to be re-used in a loop. Is it ok to std::move elements out? If I moved the ith element out, then ith slot goes into an undefined but valid state, but what about the vector? Is its state still defined and valid? Also, can I clear() and then reuse the vector in the next iteration?

EDIT: please read the question before you flag for duplication. I'm asking the state of v2 after doing std::move(v2[0]), not std::move(v2). Also I reuse v2 after I did v2.clear(). How is that similar to the suggested duplication?

EDIT: code example:

struct Foo {
    string data;
    /* other data memebers */
    void workOnData();
}

std::vector<std::string> buffer;
Foo foo;
while (1) {
    buffer.clear();
    loadData(buffer); // push data to buffer, at least one element in buffer guaranteed
    foo.data.assign(std::move(buffer[0])); // please don't ask is Foo necessary or why workOnData has to be a member method. THIS IS A SIMPLIFIED EXAMPLE!
    foo.workOnData();
}

Upvotes: 35

Views: 12790

Answers (2)

bobobobo
bobobobo

Reputation: 67306

You can move an object out of a vector, but it isn't likely done how you'd expect

You have to use a std::move_iterator to do it. Constructing a std::move_iterator is possible on any container using std::make_move_iterator as follows:

auto print = [](const vector<string> &vec) {
  for( auto&& s : vec )
    puts( s.c_str() );
};
vector<string> v = { "A string", "Another one" };
puts( "Your strings:" );
print( v );

// MOVE begin element. Good place for auto? Maybe not even!
std::move_iterator< std::vector<string>::iterator > it = std::make_move_iterator( v.begin() );
puts( "Making the iterator doesn't move anything yet" );
print( v );

string moved = *it;
puts( "Dereferencing the move iterator moves the element it points to" );
print( v );

// Note: if you receive the result of the move_iterator
// into a string&&, it won't actually move it (seems to only alias it)

Extended example

Upvotes: 0

Benjamin Lindley
Benjamin Lindley

Reputation: 103741

Is it ok to std::move elements out?

Yes, it's okay.

If I moved the ith element out, then ith slot goes into an undefined but valid state

It leaves the element in a valid but unspecified state. The difference between those two words is important in C++, but probably not too important to this question. Just thought I should point it out.

but what about the vector?

The vector is in a valid and well-specified state, though one of its elements is in an unspecified state.

Also, can I clear() and then reuse the vector in the next iteration?

Yes. Of course. Though you can do a lot more than that. Unlike a moved-from vector, you can still count on the vector having the same size, the same capacity, and all elements other than the one you just moved from remaining unchanged. As well as all references and iterators to elements (including the one you just moved from) remaining valid.

Upvotes: 41

Related Questions