用于 std::reverse() 的 C++11 便利包装器
Posted
技术标签:
【中文标题】用于 std::reverse() 的 C++11 便利包装器【英文标题】:C++11 Convenience wrapper for std::reverse() 【发布时间】:2012-04-19 10:52:10 【问题描述】:这是使用 C++11 右值引用和移动语义为std::reverse()
实现便利包装器的正确方法吗?
template <class BIDirContainer> inline BIDirContainer&& reverse(BIDirContainer a)
std::reverse(begin(a), end(a));
return std::move(a);
代码在我的测试用例中有效,但我不确定它的性能:我应该在这里使用&&
还是不必要的?
【问题讨论】:
【参考方案1】:如果您通过(右值)引用返回,那么您将获得一个悬空引用,因为a
是一个本地对象。按值返回,一切都应该“正常工作”。
【讨论】:
@Nordlöw 不需要移动,除非BIDirContainer
没有移动构造函数的实现。请参阅下面的答案。
在 C++11 中,如果您按值返回本地对象(例如本例中的 a
),那么在第一个实例中编译器应将其直接构造为返回值,并且失败如果有的话,它应该使用移动构造函数。【参考方案2】:
我想说正确的做法是从你的函数中按值返回:
template <class BIDirContainer> inline BIDirContainer reverse(BIDirContainer a)
std::reverse(begin(a), end(a));
return a;
然后给BIDirContainer
一个移动构造函数,如果它没有的话。那么这种表达方式:
BIDirContainer x = ...;
BIDirContainer backwardsreverse(x);
应该将reverse
函数中临时a
的内容移动到backwards
。
【讨论】:
所以对于 STL 容器(已经移动构造函数支持),正确的方法是既不使用&&
也不使用std::move
,对吧?
@Nordlöw 在您的函数中都不使用它们,如果您正在实现移动构造函数,则仅在您的类中使用它们。如果您使用的是 C++11 容器,则无需执行任何操作。【参考方案3】:
所以如果要修改参数...
template <class BIDirContainer>
inline BIDirContainer& reverse(BIDirContainer& a)
std::reverse(begin(a), end(a));
return a;
如果您想制作反向副本,那么:
template <class BIDirContainer>
inline BIDirContainer reverse(BIDirContainer a)
std::reverse(begin(a), end(a));
return a;
函数的返回值已经是一个右值(特别是“xvalue”)。如果您将它传递给具有移动语义的函数,它将被移动 - 但是由于上面的命名返回值优化 (NRVO) result
甚至可以就地构造(比移动语义更好)。
【讨论】:
当你通过ref时,为什么需要返回它? 这如何解释右值引用? @Jagannath:在第一个版本中,ref 是返回,因此您可以像 ostream 一样链接调用。我添加了更多细节。 是的,您对第一个版本是正确的。但是对于第二个,仅按值获取参数就足够了。以上是关于用于 std::reverse() 的 C++11 便利包装器的主要内容,如果未能解决你的问题,请参考以下文章