Imagine that I have a class whose main responsibility is to populate a data container. I would like to move the data out of this class. So I have:
class cCreator
{
public:
void generate()
{
///generate the content of data_ and populate it
....
....
}
//variation 1
std::vector<int>&& getData1()
{
return std::move(data_);
}
//variation 2
std::vector<int> getData2()
{
return std::move(data_);
}
private:
std::vector<int> data_
};
S what is the difference between variation 1 and variation 2 of getData(). What changes when I omit && from the function definition??
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.
A: You should use std::move if you want to call functions that support move semantics with an argument which is not an rvalue (temporary expression).
Std::move is not faster than straight up copying. So as the title says; i have an implementation where i copy big objects and thought std::move would give a huge performance boost over straight up copying, but it didn't (was roughly the same time).
Move Constructor And Semantics: std::move() is a function used to convert an lvalue reference into the rvalue reference. Used to move the resources from a source object i.e. for efficient transfer of resources from one object to another. std::move() is defined in the <utility> header.
In the first case, no move actually happens in the function itself. You are just returning an rvalue reference, which allows the original caller to move if needed. In the second case, the data is actually being moved into a temporary, regardless of how the caller uses the result.
cCreator c1, c2;
c1.getData1(); // no move
std::vector<int> v1 = c1.getData1(); // move directly from data_
// into v1.
c2.getData2(); // move to temporary, which isn't used.
std::vector<int> v2 = c2.getData1(); // move from data_ to temporary,
// then move from temporary to v2.
Version 1 is probably a bad idea, things like f(x.getData())
might be moving or not depending on the signature of f
. In general we want any move
to be explicit in the code, so you should at very least have something like:
std::vector<int>&& getData() &&
{
return std::move(data_);
}
So that now the move has to be explicit: f( std::move(x).getData() )
, and you probably want to provide an overload for const &
just for observing.
Version 2 would be ok if it had another name. In my experience, 99% of the people perceive getX
as a non-modifying operation. Better call it releaseData
, which is consistent with the naming of unique_ptr::release
.
I guess in this specific case where the container whose data is extracted (moved) is a stl vector, std::swap would be a valid option. So simply supplying:
const std::vector<int>& getData() const;
std::vector<int>& getData();
woudl enable user to safely extract the data if he so wishes. That might be only viable option if C++11 is not available for some reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With