【发布时间】:2016-01-08 15:33:51
【问题描述】:
有一个类Widget 带有默认和移动构造函数,我想编写一个函数:
- 接受
Widget类型的左值和右值作为参数, - 在内部从这个参数“移动”,例如,移动到其他一些
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-slides,第 48 页]。但是,这种方法的缺点是它需要Widget 的复制构造函数,以防传递左值参数w(至少在g++ 4.9.2 中)。
我能够找到以下解决方案来防止调用/要求复制构造函数。第一个使用左值和右值引用:
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复制构造函数? - 我应该更喜欢这两种解决方案中的哪一种?
- 对于这个问题,还有其他可能更好的解决方案吗?
【问题讨论】:
标签: c++ reference move lvalue rvalue