To enable move semantics on a std::vector
do I need to pass by value; so the compiler will not copy the element but just move them?
Example:
class data
{
public:
void setMyData(vector<string> sourceData)
{
private_data_ = sourceData;
}
private:
vector<string> private_data_;
};
CodePudding user response:
to enable move semantics on a C stl vector
You have misunderstanding about the move semantic concept.
The std::vector
itself is move constructable as it has the move constructor defined. You do not need to enable it explicitly, rather use it properly.
In the function
void setMyData(vector<string> sourceData) // copy 1
{
private_data_= sourceData; // copy 2
}
You are doing double copy. You need instead
void setMyData(vector<string> sourceData) // copy
{
private_data_= std::move(sourceData); // move
}
or you might want
void setMyData(vector<string>&& sourceData) // only accept the rvalue
{
private_data_= std::move(sourceData); // move
}
and for the second case, you call the function
setMyData(std::move(sourceData));
CodePudding user response:
I would recommend either using 2 overload of that function or even use a generic one:
#include <vector>
#include <string>
class data
{
public:
void setMyData(const std::vector<std::string>& sourceData){private_data_=sourceData;}
void setMyData(std::vector<std::string>&& sourceData){private_data_= std::move(sourceData);}
template <typename T>
void genericsetMyData(T&& source) {private_data_ = std::forward<T>(source);}
private:
std::vector<std::string> private_data_;
};
int main() {
class data a,b,c,d;
std::vector<std::string> s1,s2; const std::vector<std::string> s3;
a.setMyData(s1);
b.setMyData(std::move(s2));
c.genericsetMyData(s1);
d.genericsetMyData((std::move(s1)));
d.genericsetMyData(s3);
}
The templated one is a bit more complex since it uses a so called fowarding reference.
CodePudding user response:
I suggest the following:
#include <utility>
class data
{
public:
void setMyData(vector<string> sourceData)
{
private_data_ = std::move(sourceData);
}
private:
vector<string> private_data_;
};
And to init, you have two ways:
vector<string> myStrings{"hello", "i am", "stringies"};
data mydata;
// Type 1: Give ownership
mydata.setMyData(std::move(myStrings)); // not a single copy, but myStrings is empty
// Type 2: Copy
mydata.setMyData(myStrings); // Copy once only, and myStrings is still valid
The good thing about this technique is that you don't have to write several overloaded methods, you can choose which way you want to pass your parameter.