MyClass&& func( ... );
我知道一般情况下返回引用的危险性,但有时我们仍然这样做,不是吗?
T& T::operator=(T)
只是一个惯用的例子。但是T&& func(...)
呢?是否有任何普遍的地方可以从中获益?与编写库或API代码相比,与仅客户端代码相比可能不同。MyClass&& func( ... );
T& T::operator=(T)
只是一个惯用的例子。但是T&& func(...)
呢?是否有任何普遍的地方可以从中获益?与编写库或API代码相比,与仅客户端代码相比可能不同。有一些情况下这种写法是合适的,但这种情况相对来说比较少见。一个例子就是当你想要允许客户端从数据成员中移动时会出现这种情况,例如:
template <class Iter>
class move_iterator
{
private:
Iter i_;
public:
...
value_type&& operator*() const {return std::move(*i_);}
...
};
这是对towi的评论的补充。您永远不希望返回对本地变量的引用。但是您可能会遇到这种情况:
vector<N> operator+(const vector<N>& x1, const vector<N>& x2) { vector<N> x3 = x1; x3 += x2; return x3; }
vector<N>&& operator+(const vector<N>& x1, vector<N>&& x2) { x2 += x1; return std::move(x2); }
vector<N>&& operator+(vector<N>&& x1, const vector<N>& x2) { x1 += x2; return std::move(x1); }
vector<N>&& operator+(vector<N>&& x1, vector<N>&& x2) { x1 += x2; return std::move(x1); }
在除了两个参数都是左值的情况下,这应该可以防止任何副本(和可能的分配)。
return std::move(x2);
等方式。或者您可以编写一个到右值引用类型的强制类型转换,但这就是move
所做的事情。 - M.M不需要返回引用,只需返回值即可。一般情况下,返回引用并不危险——而返回对于局部变量的引用则是危险的。然而,返回一个右值引用在几乎所有情况下都是毫无意义的(我猜如果你正在编写std::move
之类的东西可能会有用)。
T&& operator+(const T&,T&&)
等内容应返回&&
。但现在已经没有了,在最终草案中被删除了。这就是我问的原因。 - towi如果您确定在函数退出后,引用的对象不会超出范围(例如全局对象的引用或返回类字段引用的成员函数等),则可以通过引用返回。
引用返回规则对左值和右值引用是相同的,区别在于您希望如何使用返回的引用。就我所见,通过右值引用返回很少见。
如果您有一个函数:
Type&& func();
Type&& ref_a = func();
因为它有效地将ref_a定义为Type&,因为命名的rvalue引用是一个lvalue,并且在这里不会执行任何实际的移动操作。 这很像:
const Type& ref_a = func();
除了实际的ref_a是一个非const的左值引用之外,这与前面的例子类似。
即使你直接将func()传递给另一个需要Type&&参数的函数,它也不是很有用,因为在该函数内部它仍然是一个命名引用。
void anotherFunc(Type&& t) {
// t is a named reference
}
anotherFunc(func());
func()和anotherFunc()之间的关系更像是一种“授权”,即func()同意anotherFunc()可能取得(或者说“窃取”)从func()返回的对象的所有权。但这种协议非常宽松。非const左值引用仍然可以被调用者“窃取”。实际上,很少有函数定义为接受rvalue引用参数。最常见的情况是“anotherFunc”是一个类名,而anotherFunc()实际上是一个移动构造函数。
还有一种可能的情况:当您需要解包元组并将值传递给函数时。
在这种情况下,如果您不确定复制省略是否有效,则可能会很有用。
例如:
template<typename ... Args>
class store_args{
public:
std::tuple<Args...> args;
template<typename Functor, size_t ... Indices>
decltype(auto) apply_helper(Functor &&f, std::integer_sequence<size_t, Indices...>&&){
return std::move(f(std::forward<Args>(std::get<Indices>(args))...));
}
template<typename Functor>
auto apply(Functor &&f){
return apply_helper(std::move(f), std::make_index_sequence<sizeof...(Args)>{});
}
};
这种情况相当罕见,除非你正在编写某种形式的std::bind
或std::thread
替代品。
value_type
而不是value_type&&
作为返回类型会更安全吗? - fredoverflow