如何在C++中从右值和左值参数中移动
How to move from both rvalue and lvalue arguments in C++?
有了一个带有默认和移动构造函数的类Widget
,我想写一个函数:
- 接受类型为CCD_ 2的左值和右值两者作为自变量
- 内部"移动"从此参数,例如,到某个其他
Widget
实例
例如:
Widget w;
auto p1 = pointer_from_lrvalue(Widget()); // rvalue argument
auto p2 = pointer_from_lrvalue(w); // lvalue argument
// w is guaranteed to be no longer used from now on
其中pointer_from_lrvalue()
可能看起来像:
std::unique_ptr<Widget> pointer_from_lrvalue(Widget w) {
return std::unique_ptr<Widget>(new Widget(std::move(w)));
}
这种传递值方法显示了Andrei Alexandrescu在其scopeGuard()
函数[ErrorHandling幻灯片,第48页]中的表现。然而,这种方法的缺点是,在传递左值参数w
(至少对于g++4.9.2)的情况下,它需要Widget
的复制构造函数
我能够找到以下解决方案来防止调用/需要复制构造函数。第一个使用左值和右值引用:
std::unique_ptr<Widget> pointer_from_lrvalue(Widget& w) {
return std::unique_ptr<Widget>(new Widget(std::move(w)));
}
std::unique_ptr<Widget> pointer_from_lrvalue(Widget&& w) {
return std::unique_ptr<Widget>(new Widget(std::move(w)));
}
第二个使用通用参考:
template <typename T>
std::unique_ptr<std::remove_reference_t<T>> pointer_from_lrvalue(T&& t) {
return std::unique_ptr<std::remove_reference_t<T>>
(new std::remove_reference_t<T>(std::move(t)));
}
我想知道:
- 这些解决方案是否正确,并且保证不会调用
Widget
副本构造函数 - 我应该更喜欢这两种解决方案中的哪一种
- 这个问题还有其他可能更好的解决方案吗
-
是的,它们都是正确的,并且保证只调用移动。
-
这是相当主观的。我个人更喜欢转发参考,因为我讨厌代码重复。但是,它确实需要将代码放入标头中。
-
如果你想变得花哨,你可以创建自己的非模板"可移动
Widget
参考:"class WidgetMover { Widget& widget; public: Widget&& moveWidget() { return std::move(widget); } WidgetMover(Widget &w) : widget(w) {} WidgetMover(Widget &&w) : widget(w) {} }; std::unique_ptr<Widget> pointer_from_lrvalue(WidgetMover w) { return std::unique_ptr<Widget>(new Widget(w.moveWidget())); }
必须注意确保
WidgetMover
的寿命不会超过其可能初始化的右值的寿命。
相关文章:
- 返回值优化:显式移动还是隐式
- 按值 C++ 返回时进行双倍移动
- 移动赋值运算符;尝试引用已删除的函数.我该如何解决这个问题?
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 移动构造函数和右值引用
- 对 r 值使用移动赋值运算符时的异常
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- 复制省略并在返回值中移动语义
- 为什么可以使用已删除的移动构造函数和赋值运算符移动对象?
- 将引用(右值)移动到函数
- 尝试根据移动赋值编写移动构造函数
- 右值可以移动到shared_ptr中吗?
- 在 c# 中将 int 添加到字符以将其 ascii 值向上移动(就像在 c++ 中一样)
- 可以从r值引用移动到临时的子对象吗
- 使用右值引用移动临时值
- 可以将std::function从右值引用移动构造到临时函数对象吗?
- 正确命名的临时变量和右值-引用/移动
- c++统一赋值操作符移动语义
- 右值和移动
- 传递值和移动,或两种方法