Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move Semantics for std::vector member

I want to ensure that I properly understand this. I ask it here since it I have not fund it spelled out explicitly.

For example I have a triangle mesh class that is basically built like this:

class Mesh
{
public:
    struct Face 
    {
        unsigned int a;
        unsigned int b;
        unsigned int c;
    };
//... 
private:
    std::string            file;
    std::vector<glm::vec3> vertices;
    std::vector<glm::vec3> normals;
    std::vector<glm::vec2> texcoord;
    std::vector<Face>      faces;   
}

Since the data in the mesh can get quite large I want to implement proper move semantics. For pointer types I fully understand this, but to trigger the rvalue constructor I need to use move, right?

For example the rvalue constructor will be:

Mesh::Mesh(Mesh&& other)
: file(std::move(other.file)),
  vertices(std::move(other.vertices)),
  normals(std::move(other.normals)),
  texcoord(std::move(other.texcoord)),
  faces(std::move(other.faces) {}

Note: Before someone points out the obvious, the application uses in many places a share_ptr. But I don't want to artificially restrict the use of the class.

like image 444
rioki Avatar asked Oct 14 '13 09:10

rioki


1 Answers

Yes, you have to use std::move() in the move constructor, like you do. However, your move constructor exactly duplicates the default one. If your class doesn't define any of:

  • copy constructor
  • copy assignment operator
  • move assignment operator
  • destructor

then a default move constructor will be generated for you, doing exactly what you did. You're better off leaving out the definition and relying on the default one.

Even if your class defines some of the above, you can ask the compiler to generate the default move constructor:

class Mesh
{
public:
  Mesh(Mesh &&) = default;
  // the rest as before
};

That way, you don't have to define it and it will work even if you later add other members (without risk of forgetting to add them to the manual move constructor).


Unfortunately, neither of the above applies to Visual Studio 2015 or earlier, which fails to generate default move constructors and doesn't support = default for move operations. So if you're targetting VS <= 2015, you have to spell out the move constructor by hand—just like you did.

like image 59
Angew is no longer proud of SO Avatar answered Nov 09 '22 09:11

Angew is no longer proud of SO