移动std :: vector成员的语义

rio*_*oki 6 c++ c++-standard-library move-constructor c++11

我想确保我正确理解这一点.我在这里问它,因为我没有明确说明它的资金.

例如,我有一个三角形网格类,基本上是这样构建的:

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;   
}
Run Code Online (Sandbox Code Playgroud)

由于网格中的数据可能变得非常大,我想实现适当的移动语义.对于指针类型我完全理解这一点,但要触发rvalue构造函数我需要使用move,对吧?

例如,rvalue构造函数将是:

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) {}
Run Code Online (Sandbox Code Playgroud)

注意:在有人指出明显的情况之前,应用程序在很多地方使用share_ptr.但我不想人为地限制班级的使用.

Rei*_*ica 14

是的,你必须std::move()在移动构造函数中使用,就像你一样.但是,您的移动构造函数完全复制了默认构造函数.如果您的班级没有定义任何:

  • 复制构造函数
  • 复制赋值运算符
  • 移动赋值运算符
  • 析构函数

然后将为您生成一个默认的移动构造函数,完全按照您的方式执行.你最好省略定义并依赖默认定义.

即使你的类定义了上面的一些,你也可以要求编译器生成默认的移动构造函数:

class Mesh
{
public:
  Mesh(Mesh &&) = default;
  // the rest as before
};
Run Code Online (Sandbox Code Playgroud)

这样,您不必定义它,即使您稍后添加其他成员也可以工作(没有忘记将它们添加到手动移动构造函数的风险).


遗憾的是,以上这两种情况都不适用于Visual Studio 2015或更早版本,它无法生成默认移动构造函数,也不支持= default移动操作.因此,如果您的目标是VS <= 2015,则必须手动拼出移动构造函数 - 就像您一样.

  • 我真的很欣赏这里的明确答案,以及有关使用带有 default 关键字的默认版本的信息。谢谢你! (2认同)