从lambda返回对象/右值ref的首选形式

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

本文关键字:ref 右值 lambda 返回 对象      更新时间:2023-10-16

如果我有一个实现move语义的类:

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

在lambda中返回BigObject的正确方法是什么?

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

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

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

还是其他形式?

谢谢。

第一种形式和第三种形式基本相同,因为return BigObject(x);是右值,因此已经调用了move构造函数。

然而,第二种形式调用了未定义的行为,因为右值引用仍然只是一个引用,而对超出作用域的东西的引用仍然和以前一样糟糕。

第一种形式很好。作为一般规则,never, ever返回右值引用。第三种形式不需要移动,因为BigObject(x)已经是右值了。