Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prefered form for returning an object/rvalue ref, from a lambda

If I have a class implementing move semantics:

class BigObject
{
public:
    BigObject(something x = something()) { ... }
    BigObject(const BigObject& other) { ... }
    BigObject(BigObject&& other) { ... }
    BigObject& operator=(BigObject other) { ... }
    void swap(BigObject& other) { ... }
    // [...]
};


auto begin = std::begin(somethingSequence); // collection doesn't matter here
auto end = std::end(somethingSequence); // collection doesn't matter here

BigObjectOutputIterator dest; // collection doesn't matter here

What is the correct way to do return a BigObject in a lambda?

std::transform(begin, end, dest, 
    [](something x) -> BigObject {return BigObject(x); });

or

std::transform(begin, end, dest, 
    [](something x) -> BigObject&& {return std::move(BigObject(x)); });

or

std::transform(begin, end, dest, 
    [](something x) -> BigObject {return std::move(BigObject(x)); });

or some other form?

Thanks.

like image 325
utnapistim Avatar asked Apr 26 '26 19:04

utnapistim


2 Answers

The first and third form are basically the same, since return BigObject(x); is an rvalue and as such the move constructor is called already.

The second form however invokes undefined behaviour, as an rvalue reference is still just a reference, and a reference to something that goes out of scope is still as bad as it was before.

like image 149
Xeo Avatar answered Apr 29 '26 08:04

Xeo


The first form is just fine. As a general rule, never, ever, return rvalue references. The third form doesn't need the move, as BigObject(x) is already an rvalue.

like image 20
Puppy Avatar answered Apr 29 '26 08:04

Puppy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!