阅读一些基于范围的循环的例子,他们提出了两种主要方式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,示例建议使用第二个版本(按值) . 为什么他们没有提出 const
引用的内容(至少我没有找到任何直接的建议):
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
}
Isn 't it better? Doesn' t它避免了每次迭代中的冗余副本,而它是 const
?
4 回答
如果您不想更改项目以及想要避免复制,那么
auto const &
是正确的选择:谁建议你使用
auto &
是错误的 . 别理他们 .这是概述:
如果要处理副本,请选择
auto x
.如果要使用原始项目,请选择
auto &x
,并可以对其进行修改 .如果要使用原始项目,请选择
auto const &x
,不会修改它们 .如果您有
std::vector<int>
或std::vector<double>
,那么使用auto
(带值复制)而不是const auto&
就可以了,因为复制int
或double
很便宜:但是如果你有一个
std::vector<MyClass>
,其中MyClass
有一些非平凡的复制语义(例如std::string
,一些复杂的自定义类等),那么我建议使用 const auto& to avoid deep-copies :然后他们给出了错误的建议 .
因为他们给出了错误的建议:-)你提到的是正确的 . 如果您只想要 observe 一个对象,则无需创建副本,也无需对其进行非
const
引用 .EDIT:
我看到你链接的引用都提供迭代一系列
int
值或其他一些基本数据类型的例子 . 在这种情况下,由于复制int
并不昂贵,因此创建副本基本上等同于(如果不是更有效)观察const &
.但是,对于用户定义的类型,通常不是这种情况 . 复制UDT可能很昂贵,如果您没有理由创建副本(例如修改检索到的对象而不更改原始副本),则最好使用
const &
.我将在这里反对并说在基于循环的范围内不需要
auto const &
. 如果您认为以下函数是愚蠢的(不是出于其目的,而是出现在它的编写方式),请告诉我:这里,作者创建了一个对
v
的const引用,用于所有不修改v的操作 . 在我看来,这是愚蠢的,并且可以使用auto const &
作为基于for循环的范围中的变量进行相同的参数只是auto &
.