Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What lasts after using std::move c++11

Tags:

c++

c++11

After using std::move in a variable that might be a field in a class like:

class A {
  public:
    vector<string>&& stealVector() {
      return std::move(myVector);
    }
    void recreateMyVector() {
    }
  private:
    vector<string> myVector;        
};

How would I recreate the vector, like a clear one? What is left in myVector after the std::move?

like image 629
Nezquick Avatar asked Dec 31 '13 01:12

Nezquick


People also ask

What happens to object after std :: move?

std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.

What is left after Std move?

For std types (and only those), the standard specifies that a moved-from object is left in the famous "valid, but unspecified" state.

Do I need to return std :: move?

std::move is totally unnecessary when returning from a function, and really gets into the realm of you -- the programmer -- trying to babysit things that you should leave to the compiler.

Can I use variable after std :: move?

You must not use a variable after calling std::move() on it.


2 Answers

The common mantra is that a variable that has been "moved-from" is in a valid, but unspecified state. That means that it is possible to destroy and to assign to the variable, but nothing else.

(Stepanov calls this "partially formed", I believe, which is a nice term.)


To be clear, this isn't a strict rule; rather, it is a guideline on how to think about moving: After you move from something, you shouldn't want to use the original object any more. Any attempt to do something non-trivial with the original object (other than assigning to it or destroying it) should be carefully thought about and justified.

However, in each particular case, there may be additional operations that make sense on a moved-from object, and it's possible that you may want to take advantage of those. For example:

  • The standard library containers describe preconditions for their operations; operations with no pre­conditions are fine. The only useful ones that come to mind are clear(), and perhaps swap() (but prefer assignment rather than swapping). There are other operations without preconditions, such as size(), but following the above reasoning, you shouldn't have any business inquiring after the size of an object which you just said you didn't want any more.

  • The unique_ptr<T, D> guarantees that after being moved-from, it is null, which you can exploit in a situation where ownership is taken conditionally:

    std::unique_ptr<T> resource(new T);
    std::vector<std::function<int(std::unique_ptr<T> &)> handlers = /* ... */;
    
    for (auto const & f : handlers)
    {
        int result = f(resource);
        if (!resource) { return result; }
    }
    

    A handler looks like this:

    int foo_handler(std::unique_ptr<T> & p)
    { 
        if (some_condition))
        {
            another_container.remember(std::move(p));
            return another_container.state();
        }
        return 0;
    }
    

    It would have been possible generically to have the handler return some other kind of state that indi­cates whether it took ownership from the unique pointer, but since the standard actually guaran­tees that moving-from a unique pointer leaves it as null, we can exploit that to transmit that information in the unique pointer itself.

like image 173
Kerrek SB Avatar answered Nov 16 '22 03:11

Kerrek SB


Move the member vector to a local vector, clear the member, return the local by value.

std::vector<string> stealVector() {
    auto ret = std::move(myVector);
    myVector.clear();
    return ret;
}
like image 44
Benjamin Lindley Avatar answered Nov 16 '22 02:11

Benjamin Lindley