在修改潜在r值参考的函数中,正确的返回值是多少?

时间:2017-08-09 20:28:45

标签: c++11 move rvalue-reference perfect-forwarding

从概念上和实践上,返回潜在获取r值参考的函数的修改值的正确方法是什么。

template<class Vector>
??? add_element(Vector&& v){
    v.emplace_back(1.);
    return ???(v);
}

Intuition告诉我这个,(因为我不会丢失原始类型的信息)

template<class Vector>
Vector&& add_element(Vector&& v){
    v.emplace_back(1.);
    return std::forward<Vector>(v);
}

但其他可能性是

template<class Vector>
Vector& add_element(Vector&& v){
    v.emplace_back(1.);
    return v;
}

甚至是这些,(基于此https://pizer.wordpress.com/2009/04/13/c0x-do-people-understand-rvalue-references/

template<class Vector>
Vector // or typename std::decay<Vector>::type 
add_element(Vector&& v){
    v.emplace_back(1.);
    return v; // or std::forward<Vector>(v); 
}

返回修改后的传递参数的最通用方法是什么?

1 个答案:

答案 0 :(得分:5)

在转发引用的更一般情况下,您的返回方式取决于您想要做什么。

幸运的是,在这种情况下,除了一个之外的所有选择都是错误的(危险的,脆弱的等),因此这样做很容易,因为你正在返回一个容器。

template<class Vector>
Vector add_element(Vector&& v){
  v.emplace_back(1.);
  return std::forward<Vector>(v); 
}
这是我通常做的事情。它可能需要一个临时的,如果是,则将临时值移动到返回值。

如果它是非临时的,它会修改它并返回相同类别的引用。

template<class Vector>
Vector&& add_element(Vector&& v){
  v.emplace_back(1.);
  return std::forward<Vector>(v); 
}

这是一个不幸的想法。参考生命周期扩展不会通过函数调用进行通勤,因此

auto&& v = add_element(make_vector());

导致泄漏参考。假设您的类型移动便宜(如向量),返回移入的临时副本是一项微不足道的成本,可以实现参考生命周期扩展。

&#34;但是&#34;,你说,&#34;我不会使用auto&&&#34;。好吧,对于容器,for(:)循环,并且引用悬空。因此,作为规则,永远不会通过右值引用返回容器

template<class Vector>
Vector& add_element(Vector&& v){
  v.emplace_back(1.);
  return v;
}

这会丢失类型信息并阻止参考生命周期延长。

如果可以提供帮助,请不要通过&返回临时。

传递左值时表现得很奇怪:

template<class Vector>
std::decay_t<Vector> add_element(Vector&& v){
  v.emplace_back(1.);
  return std::forward<Vector>(v); 
}

因为它复制并修改了它的参数。我不确定你为什么要这样做。