转发转发引用的个别成员
Forward individual members of a Forward reference
我有一个函数可以通过其成员移动通用参数。以下哪个选项更正确:
这看起来更自然但很奇怪,因为参数可能会移动两次 [a],这很奇怪,因为对象可能变得无效。
template<class T>
void fun(T&& t){
myhead_ = std::forward<T>(t).head_;
myrest_ = std::forward<T>(t).rest_;
}
这不可能是错误的,但它可能没有移动任何东西。
template<class T> void fun(T&& t){
myhead_ = std::forward<decltype(t.head_)>(t.head_);
myrest_ = std::forward<decltype(t.rest_)>(t.rest_);
}
这似乎是正确的,但是代码太多了。
template<class T> void fun(T& t){
myhead_ = t.head_;
myrest_ = t.rest_;
}
template<class T> void fun(T&& t){
myhead_ = std::move(t.head_);
myrest_ = std::move(t.rest_);
}
[a] 正如@Angew 指出的那样,这个说法是不正确的,它只是看起来 好像移动了两次。 std::forward
(如 std::move
)实际上并没有移动任何东西。至多成员被移动(通过后续操作 decltype(myhead)::operator=
但这正是 objective。)
您的第一个代码非常好:
template<class T>
void fun(T&& t){
myhead_ = std::forward<T>(t).head_;
myrest_ = std::forward<T>(t).rest_;
}
那是因为标准保证当做a.b
和a
时是一个xvalue(比如转发的右值引用),a.b
的结果也是一个exvalue(即可以移动)。另请注意,std::forward
和 std::move
本身不执行任何实际的 moving,它们只是强制转换。因此,在您的代码中两次从 t
移动是没有风险的。
我有一个函数可以通过其成员移动通用参数。以下哪个选项更正确:
这看起来更自然但很奇怪,因为参数可能会移动两次 [a],这很奇怪,因为对象可能变得无效。
template<class T> void fun(T&& t){ myhead_ = std::forward<T>(t).head_; myrest_ = std::forward<T>(t).rest_; }
这不可能是错误的,但它可能没有移动任何东西。
template<class T> void fun(T&& t){ myhead_ = std::forward<decltype(t.head_)>(t.head_); myrest_ = std::forward<decltype(t.rest_)>(t.rest_); }
这似乎是正确的,但是代码太多了。
template<class T> void fun(T& t){ myhead_ = t.head_; myrest_ = t.rest_; } template<class T> void fun(T&& t){ myhead_ = std::move(t.head_); myrest_ = std::move(t.rest_); }
[a] 正如@Angew 指出的那样,这个说法是不正确的,它只是看起来 好像移动了两次。 std::forward
(如 std::move
)实际上并没有移动任何东西。至多成员被移动(通过后续操作 decltype(myhead)::operator=
但这正是 objective。)
您的第一个代码非常好:
template<class T>
void fun(T&& t){
myhead_ = std::forward<T>(t).head_;
myrest_ = std::forward<T>(t).rest_;
}
那是因为标准保证当做a.b
和a
时是一个xvalue(比如转发的右值引用),a.b
的结果也是一个exvalue(即可以移动)。另请注意,std::forward
和 std::move
本身不执行任何实际的 moving,它们只是强制转换。因此,在您的代码中两次从 t
移动是没有风险的。