Home > Software engineering >  std::vector and move semantics
std::vector and move semantics

Time:10-27

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.

  • Related