从概念上和实践上,返回潜在获取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);
}
返回修改后的传递参数的最通用方法是什么?
答案 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);
}
因为它复制并修改了它的参数。我不确定你为什么要这样做。