基于C ++ 11范围的循环:按值或引用const获取项目
阅读一些基于范围的循环的例子,他们提出了两种主要的方法1,2,3,4
std::vector<MyClass> vec; for (auto &x : vec) { // x is a reference to an item of vec // We can change vec's items by changing x }
要么
for (auto x : vec) { // Value of x is copied from an item of vec // We can not change vec's items by changing x }
好。
当我们不需要更改vec
项目时,IMO示例build议使用第二个版本(按值)。 为什么他们不提出一些const
参考(至less我还没有find任何直接的build议):
for (auto const &x : vec) // <-- see const keyword { // x is a reference to an const item of vec // We can not change vec's items by changing x }
不好吗? 它不是避免每个迭代中的冗余副本,而它是一个const
?
如果您不想更改项目以及想要避免复制,那么auto const &
是正确的select:
for (auto const &x : vec)
谁build议你使用auto &
是错误的。 别理他们。
这里回顾一下:
- select
auto x
当你想处理副本。 - 当您想要使用原始项目并select修改时,请select
auto &x
。 - 当您想要使用原始项目时,请select
auto const &x
并且不会修改它们。
如果你有一个std::vector<int>
或std::vector<double>
,那么使用auto
(用值拷贝)代替const auto&
就好了,因为复制一个int
或者double
是便宜的:
for (auto x : vec) ....
但是如果你有一个std::vector<MyClass>
,其中MyClass
有一些非平凡的复制语义(例如std::string
,一些复杂的自定义类等),那么我build议使用const auto&
来避免深拷贝 :
for (const auto & x : vec) ....
当我们不需要更改
vec
项目时,示例build议使用第一个版本。
然后他们给出了一个错误的build议。
为什么他们不build议引用的东西
因为他们提出了错误的build议:-)你提到的是正确的。 如果您只想观察一个对象,则不需要创build副本,也不需要非常量引用。
编辑:
我看到你链接的引用都提供了遍历一系列int
值或其他基本数据types的例子。 在这种情况下,因为复制一个int
并不昂贵,所以创build一个副本基本上等价于(如果不是更有效率),那么就有一个观察const &
。
但是,对于用户定义的types,通常情况并非如此。 UDT的复制可能是昂贵的,如果你没有创build副本的原因(例如修改检索的对象而不改变原来的),那么最好使用const &
。
我将在这里相反,并说没有必要为auto const &
在基于循环范围。 告诉我,如果你认为下面的函数是愚蠢的(不是为了它的目的,而是写它的方式):
long long SafePop(std::vector<uint32_t>& v) { auto const& cv = v; long long n = -1; if (!cv.empty()) { n = cv.back(); v.pop_back(); } return n; }
在这里,作者已经创build了一个v
的const引用,用于所有不修改v的操作。在我看来,这是愚蠢的,并且可以使用auto const &
作为基于循环,而不是只是auto &
。