How to use move semantics when returning a member variable?

I am implementing a factory class that builds the uint8_t vector. I want to use move semantics when returning the resulting vector. This seems to work, but I'm not sure if this is the right way to accomplish what I want.

I have seen quite a few examples of how the returned automatic variable will be treated as an rvalue and use the move code constructor of the calling code, but in my example, the returned object is a member. I know that a member will lose its contents if the caller places the return value in the move constructor - and that is exactly what I want.

I wrote it something like this:

#include <cstdint> #include <iostream> #include <vector> class Factory { public: std::vector<uint8_t> _data; Factory(std::size_t size) : _data(size, 0) { } void buildContent(int param) { // perform operations on the contents of _data } std::vector<uint8_t> && data() { return std::move(_data); } }; int main() { Factory factory(42); factory.buildContent(1); std::vector<uint8_t> temp(factory.data()); std::cout << "temp has " << temp.size() << " elements" << std::endl; std::cout << "factory._data has " << factory._data.size() << " elements" << std::endl; return 0; } 

Edit:

Oh, and the sample code outputs the following:

 temp has 42 elements factory._data has 0 elements 
+7
c ++ c ++ 11 move-semantics
source share
3 answers

First of all, you need to decide what you want. Are you sure you want to suck data from your instance? If so, what you do is fine. On the other hand, it looks rather unsafe. What you can do is use reference qualifiers to ensure that you return only the rvalue link when the instance itself is a rvalue reference:

 std::vector<uint8_t> && data() && // called on rvalue { return std::move(_data); } // return lvalue ref or value std::vector<uint8_t>& data() & // called on lvalue { return _data; } 

In the end, it all depends on what problem you are trying to solve, which is not obvious from your question.

+5
source share

If your compiler has rvalue references to this ( && after methods), you can use it. See Reply @juanchopanza.

If you do not, first make sure that data() makes it clear that you are moving. There are several ways to do this.

First, non-member ( friend s) methods can be overridden by && . So you can get this syntax:

 std::vector<uint8_t> temp(get_data( std::move(factory) ); 

where get_data has && and & overloads on your factory type, and either moves or doesn't rely on it.

Then you want to return std::vector<uint8_t> instead of `std::vector<uint8_t>&& to extend the life. The execution cost is somewhere between zero and small, but the errors to be fixed are worth it.

If create_factory returns a factory object, then if we do this:

 for( uint8_t x : get_data( create_factory() ) ) 

get_data , which returns && , does not work, and one that returns temporary works flawlessly.

What's happening? Well, range-based loops are defined as linking what you iterate over the link. A temporary link to a link has an extended lifespan: a link tied to a link does not have a life extension. The lifetime of the return value of the create_factory function create_factory not increase in both cases.

In the case of && reference to the vector remains dangling. With the back-and-forth case, the factory vector moves to the temporary one, then this lifetime increases.

In short, returning && links is very rarely a good idea.

+1
source share

How about hiding the assignment operator in your vector and only implement the move assignment operator (essentially disallow copying - if that's what you want).

To this:

 std::vector<uint8_t> temp(factory.data()); 

will not compile unless you change it to the following:

 std::vector<uint8_t> temp(std::move(factory)); 
0
source share

All Articles