PolGraphic
PolGraphic

Reputation: 3364

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

I wonder if I use the move semantic correctly:

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)){}
};

What will I achieve here with move? The code for comparison (I could the const & too):

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){}
};

How many copies will be prevented and which of them will happen anyway?

I would like to use the code like this:

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

Could I optimize it further?

Upvotes: 1

Views: 77

Answers (1)

David
David

Reputation: 28178

I wonder if I use the move semantic correctly:

By accepting only rvalue referencing you are restricting passing lvalues to this constructor. You would probably find out pretty quickly you can't use this like you would expect. If you accept the types by value...

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)}
{}

... you allow the user of the class to move or copy into the constructor variable, and then you always move into your member variable. This means you will always cause 1 copy and 1 move or 2 moves depending on how the ctor was called. Alternatively you could take by const& and always cause exactly 1 copy no matter what. If you want to be the undeniably fastest you would have overloads for every combination of && and const&, but that's too much code.

What will I achieve here with move?

Making an assumption that a Point3D contains just 3 ints/floats/doubles, you won't gain anything. Fundamental types don't get anything from move, it's the same as a copy.

The biggest benefit from moving is usually when you can 'steal' dynamically allocated memory. Think of a vector, it dynamically allocates an array and holds a pointer to it. When you move it, it can simply copy that pointer to the new object and null out the original pointer. When you copy it, it allocates new memory in the new object and copies the array (possibly element by element) into the new array. Big cost difference: an allocation and copying the elements of an array compared to just copying a pointer.

Conclusion: For your types, passing by const& is likely the fastest way to go.

Upvotes: 1

Related Questions