9

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.

6
  • 1
    I think you understood it correctly, your code looks fine to me. (Except the missing closing bracket, but I think that's a copy/paste error, right?) Commented Oct 14, 2013 at 10:00
  • 6
    Note that the compiler generated or defaulted move constructor would do that for you. Commented Oct 14, 2013 at 10:01
  • glm::vec3, glm::vec2 are what ? If they are classes then they should implement move semantics as well. Commented Oct 14, 2013 at 10:09
  • 3
    @Jagannath That doesn't matter as the vector itself is moved, this means that the elements are not copied or moved at all. Commented Oct 14, 2013 at 10:14
  • 1
    @Jagannath Why? Moving the entire std::vector will just transfer the internal buffer ownership. Sure, they would benefit from it for when the vectors are resized, but it's not necessary for Mesh's own move ctor. Commented Oct 14, 2013 at 10:16

1 Answer 1

20

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I really appreciate the clear answer here, as well as the information about using the default versions with the default keyword. Thank You!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.