我是否正确地使用了move语义?好处是什么?

Do I use the move semantic correctly? What would be the benefit?

本文关键字:语义 是什么 move 是否 正确地      更新时间:2023-10-16

我想知道我是否正确使用move语义:

class Vertex{
    protected:
        Common::Point3D position;
        Common::Point3D normal;
        Common::Point2D uv;
        Common::Point2D tangent;
    public:
        Vertex(Common::Point3D &&position, Common::Point3D &&normal, Common::Point2D &&uv, Common::Point2D &&tangent)
            : position(std::move(position)), normal(std::move(normal)), uv(std::move(uv)), tangent(std::move(tangent)){}
};

我将在这里实现什么move ?用于比较的代码(我也可以const &):

class Vertex{
    protected:
        Common::Point3D position;
        Common::Point3D normal;
        Common::Point2D uv;
        Common::Point2D tangent;
    public:
        Vertex(Common::Point3D position, Common::Point3D normal, Common::Point2D uv, Common::Point2D tangent)
            : position(position), normal(normal), uv(uv), tangent(tangent){}
};

将阻止多少副本,哪些副本无论如何都会发生?

我想使用这样的代码:

Vertex * vertices = new Vertex[10000];
vertices[0] = Vertex(Common::Point3D(1,2,3), Common::Point3D(4,5,6)...);
vertices[1] = ...

我可以进一步优化它吗?

我想知道我是否正确使用移动语义:

通过只接受右值引用,您限制了向此构造函数传递左值。你可能很快就会发现你不能像你期望的那样使用它。

Vertex(Common::Point3D position, Common::Point3D normal, Common::Point2D uv, Common::Point2D tangent)
    : position{std::move(position)}
    , normal{std::move(normal)}
    , uv{std::move(uv)}
    , tangent{std::move(tangent)}
{}

…允许类的用户将movecopy放入构造函数变量,然后始终将move放入成员变量。这意味着你将总是导致1次复制和1次移动或2次移动,这取决于如何调用该actor。或者,你可以采取const&,无论如何,总是只复制1份。如果你想成为不可否认的最快的,你可以为&&const&的每一个组合设置重载,但那代码太多了。

我在这里用move会得到什么?

假设Point3D只包含3个整型/浮点型/双精度型,你不会获得任何东西。基本类型不会从move中获得任何东西,它与副本相同。

移动的最大好处通常是可以"窃取"动态分配的内存。想象一下vector,它动态地分配一个数组并保存指向该数组的指针。当你move它,它可以简单地复制指针到新对象和空原指针。当您复制它时,它会在新对象中分配新的内存,并将数组(可能逐个元素)复制到新数组中。巨大的成本差异:与仅仅复制指针相比,分配和复制数组元素。

结论:对于你的类型,通过const&可能是最快的方法。