Question

Which set methods has better performance in compiler supporting right-value: with or without const&? For example

class A
{
public:
    void setProperty(Property const& p)   {m_property = p;}
    void setProperty(Property p)          {m_property = p;}
};

Or is keeping both okay? Here Property is a large class. The refactor tool in Visual Assist X use the second one without const&.

Was it helpful?

Solution 2

This one is better

void setProperty(Property const& p)   {m_property = p;}

It saves one copy of Property when enters setProperty function, it only copies a reference to Property which is very cheap.

OTHER TIPS

Write the setter to take a const&:

void setProperty(Property const& p) {m_property = p;}

and in C++11, write an overload that takes && as well:

void setProperty(Property&& p) {m_property = std::move(p);}

It's nice to use the "shortcut" method of writing a single overload that takes the property by value:

void setProperty(Property p) {m_property = std::move(p);}

but be aware that when passed an lvalue, this requires memory to be allocated simultaneously for 3 objects - the original, the member, and the parameter - for a short time.

If you're feeling especially jaunty, you can amaze your friends and family by writing a perfect forwarding setter:

template <typename T>
void setProperty(T&& t) {m_property = std::forward<T>(t);}

which subsumes both the const& and && case, as well as being capable of accepting any type that is assignable to m_property. Be aware that this is hell on readability, and results in "interesting" error messages when misused.

The question can only be answered by looking at the Property type. If it implements move operations, then the best approach is to take the argument by value and move it internally:

void setProperty(Property p)   {m_property = std::move(p);}

If the argument is an lvalue, the copy will be done in the interface, and you will move the value internally, and the cost will be one copy and one move (moves should be cheap). If the argument to the function is a temporary, the compiler can elide the copy (and if it doesn't, it must move rather than copy). Then the function will perform another move internally for a total cost of one (or two) move operations, which are cheap.

If you had passed by const&, then in the case where the argument is a temporary, the compiler would not be able to elide the copy and you would pay for two copies.

Regarding the suggestion to use perfect forwarding, if you have access to the interface of the Property type (which you should, since you are holding a member), there is no need to make the setter a template, as that will generate unnecessary extra code in the final executable and unnecessary complexity for other maintainers.

When you use a constant reference, you only send a pointer to the function instead of copying the whole Object (class Property). This can save you some time, especially if the Property is big. What is more, it saves you precious memory.

However, you are not allowed to make any changes due to the const&. If you remove the const, any changes will be done to the original Object.

To sum up, if you just want to get information from the Property Object without making any changes, a constant reference (const&) is the best way to go.

In general, passing by reference is best because it saves copying the object. If the object is small with trivial copying behavior (has a few ints and default copy constructor) then the cost of copying the object is negligible. In some cases, pass by value may be faster as the optimizer knows nothing else can modify the object the function has received. As I have no idea what Property is, I would pass by reference in case it is a large or complex class. When in doubt, pass by reference.

In C++11 things can be different due to move constructors and stuff but I don't fully understand them. But you won't go far wrong with the this advice. When in doubt, pass by reference!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top