Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

c++ - Should std::move be used in return-statements for effeciency?

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...