我们什么时候需要'明确的xvalues'?

时间:2016-01-19 07:07:09

标签: c++ c++11

xvalue 的定义如下:

  

- xvalue(“eXpiring”值)也指对象,通常接近其生命周期的末尾(例如,可以移动其资源)。 xvalue是涉及rvalue引用的某些表达式的结果(8.3.2)。 [示例:调用返回类型为右值引用的函数的结果是xvalue。 - 例子]

我们是否会陷入我们实际需要使用其返回类型为右值引用的函数的位置,该函数是xvalue?

const int && Foo()
{
    // ...
}

移动语义将右值引用作为参数,而不是返回值。所以我认为不是这样的。

3 个答案:

答案 0 :(得分:5)

这正是std::move的原因 - std::move执行的结果是xvalue。除此之外很难分辨,因为在主要返回时,函数的引用在大多数情况下都是坏事。但也许有人会想出另一个聪明的用法。

答案 1 :(得分:5)

返回rvalue引用可用于已将rvalues作为参数的函数。一个简单的例子:

struct X {
    X() = default;
    X(X&& other) { std::cout << "move ctor\n"; }
    X(X const&) = delete;
    void log(std::string const& s){ std::cout << "log: " << s << "\n"; }
};

void sink(X&& x) { 
    x.log("sink"); 
}

X&& passOn(X&& in) {
    in.log("pass");
    return std::move(in);
}

X moveOn(X&& in) {
    in.log("move");
    return std::move(in);
}

int main() {
    sink(passOn(X()));
    std::cout << "===============================\n";
    sink(moveOn(X()));
}

Live demo →

第二个函数将调用move构造函数来创建返回的对象,而第一个函数将传递它已经获得的引用。如果我们不返回原始引用,而是引用引用对象的一部分,例如,这将更有用。

template<class T>
T&& getHead(std::vector<T>&& input) {
    return std::move(input.front());
}

答案 2 :(得分:3)

  

我们是否会陷入我们实际需要使用其返回类型为右值引用的函数的位置,该函数是xvalue?

它在容器类中使用,例如tuple有一个get重载,如下所示:

template< std::size_t I, class... Types >
typename std::tuple_element<I, tuple<Types...> >::type&&
    get( tuple<Types...>&& t );

我认为C ++ 17中的std::optionalstd::variant都会有类似的重载。

当然,唯一的一点是避免在某些特定情况下输入std::move,例如:

 auto x = std::get<1>( f() );

f按值返回元组。