在基于范围for循环中使用通用引用的优点是什么?
如果我想执行只读操作, const auto&
就足够了。 但是,我碰到了
for (auto&& e : v) // v is non-const
最近几次。 这让我想知道:
是否有可能在一些不起眼的angular落案例中使用通用引用有一些性能优势,与auto&
or const auto&
相比?
( shared_ptr
是一个晦涩的angular落案件的嫌疑犯)
更新我在我的collections中find的两个例子:
迭代基本types时使用const引用的任何缺点?
我可以使用基于范围的for循环轻松地迭代地图的值吗?
请专注于这个问题: 为什么我要在基于范围的for循环中使用auto &&?
我能看到的唯一优点是序列迭代器返回代理引用时,您需要以非const方式对该引用进行操作。 例如考虑:
#include <vector> int main() { std::vector<bool> v(10); for (auto& e : v) e = true; }
这不会编译,因为从iterator
返回的右值vector<bool>::reference
不会绑定到非常量左值引用。 但是这将工作:
#include <vector> int main() { std::vector<bool> v(10); for (auto&& e : v) e = true; }
尽pipe如此,除非您知道您需要满足这样的用例,否则我不会这样编写代码。 也就是说,我不会这样做,因为它确实会引起人们想知道你在做什么。 如果我确实这么做了,那么为什么要包括一个评论呢?
#include <vector> int main() { std::vector<bool> v(10); // using auto&& so that I can handle the rvalue reference // returned for the vector<bool> case for (auto&& e : v) e = true; }
编辑
我最后一个例子应该是一个有意义的模板。 如果你知道循环总是处理一个代理引用,那么auto
和auto&&
。 但是,当循环有时处理非代理引用,有时代理引用,那么我认为auto&&
将成为select的解决scheme。
使用auto&&
或通用引用与基于范围的-loop相比,您可以捕获所获取的内容。 对于大多数types的迭代器,你可能会得到一个T&
或T const&
对于某些T
types。 有趣的例子是解引用一个迭代器产生一个临时的:C ++ 2011得到了宽松的需求,迭代器不一定需要产生一个左值。 通用引用的使用匹配std::for_each()
中的参数转发:
template <typename InIt, typename F> F std::for_each(InIt it, InIt end, F f) { for (; it != end; ++it) { f(*it); // <---------------------- here } return f; }
函数对象f
可以不同地处理T&
, T const&
和T
为什么一个基于范围的循环的主体是不同的呢? 当然,要真正利用通用引用推导出types,您需要相应地传递它们:
for (auto&& x: range) { f(std::forward<decltype(x)>(x)); }
当然,使用std::forward()
意味着你接受任何从中移出的返回值。 这样的对象在非模板代码中是否有意义,我不知道(还没有?)。 我可以想象,使用通用引用可以为编译器提供更多的信息来做正确的事情。 在模板化的代码中,它没有做出关于对象应该发生什么的决定。
我几乎总是使用auto&&
。 为什么当你不必要的时候被一个边缘案例咬住? 键入的时间也更短,我只是觉得它更透明。 当你使用auto&& x
,那么你就知道x
都是x
。