I cannot figure out if the std::move in the following code does anything good or that it is completely wrong?
The class Object
has both Move and Copy constructor defined.
First: With Move:
template<typename T> template <typename F>
const Object<T> Object<T>::operator*(const F& rhs) const
{
return std::move(Object(*this) *= rhs); // We end in move constructor
}
Second: Without Move:
template<typename T> template <typename F>
const Object<T> Object<T>::operator*(const F& rhs) const
{
return Object(*this) *= rhs; // We end in copy constructor
}
The *=
operator is defined as:
template<typename T> template<typename F>
Object<T>& Object<T>::operator*=(const F& rhs)
{
for(int i = 0; i < dimension ; i++)
{
_inner[i] *= rhs;
}
return *this;
}
Here is the code i use to test it:
Object<double> test(4);
Object<double> test2(test * 4);
std::cout << test2; // works fine
Result In the first case we end in the move constructor and in the second we end in the copy constructor.
In either case the code compiles.
Is one more efficient than the other since I would assume it is faster to move the new object out instead of copying it out?
Additional info: I use the following compiler: g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3
Is one more efficient than the other since I would assume it is faster to move the new object out instead of copying it out?
Yes, using std::move
here will be more efficient, assuming the object has move semantics more efficient than copying.
Usually, when returning a temporary or a local variable, move semantics will be used automatically. However, in this case you're not directly returning the temporary, but rather the lvalue reference returned by operator*=
. Since an lvalue won't be moved, you do need std::move
in this case to turn it into an rvalue.
However, you should not return a const
value, as this prevents the return value from being used to move-initialise (or move-assign to) another object. Your example will initialise test2
by copying the return value, although that copy might be elided.
Alternatively, you could implement it using a local variable:
template<typename T> template <typename F>
Object<T> Object<T>::operator*(const F& rhs) const
{
Object lhs(*this);
lhs *= rhs;
return lhs;
}
Not only can the return value be moved, but the move itself can be elided.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With