基于范围的循环:通过值或对const的引用获取项
Range based loop: get item by value or reference to 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,示例建议使用第二个版本(按值)。为什么他们没有提出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
}
不是更好吗?当它是一个const
时,它不是避免了每次迭代的冗余复制吗?
如果您不想更改项目,并且希望避免复制,那么auto const &
是正确的选择:
for (auto const &x : vec)
建议你使用auto &
的人是错误的。忽略它们。
重述如下:
- 选择
auto x
当你想要使用副本。 - 选择
auto &x
当你想要工作的原始项目,可以修改他们。 - 选择
auto const &x
,当你想使用原始项目,不修改它们。
如果您有std::vector<int>
或std::vector<double>
,那么使用auto
(带值复制)而不是const auto&
是很好的,因为复制int
或double
是便宜的:
for (auto x : vec)
....
但是如果你有一个std::vector<MyClass>
,其中MyClass
有一些非平凡的复制语义(例如std::string
,一些复杂的自定义类等),那么我建议使用 const auto&
来避免深度复制:
for (const auto & x : vec)
....
当我们不需要更改
vec
项时,示例建议使用第一个版本。
然后他们给出了错误的建议。
为什么他们不建议const引用
因为他们给了一个错误的建议:-)你提到的是正确的。如果您只想观察对象,则不需要创建副本,也不需要对其进行非const
引用。
我看到你链接的所有参考文献都提供了迭代int
值范围或其他一些基本数据类型的示例。在这种情况下,由于复制int
并不昂贵,因此创建一个副本基本上相当于(如果不是更有效的话)拥有一个观察const &
。
const &
。
我将在这里相反地说,在基于范围的for循环中不需要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;
}
在这里,作者创建了一个对v
的const引用,用于所有不修改v的操作。在我看来,这是愚蠢的,并且可以使用auto const &
作为基于范围的for循环中的变量,而不仅仅是auto &
。
我会考虑
for (auto&& o : range_expr) { ...}
或
for (auto&& o : std::as_const(range_expr)) { ...}
总是有效的。
和注意可能的临时范围表达式陷阱。
在c++ 20中有类似
这样的东西for (T thing = foo(); auto& x : thing.items()) { /* ... */ }
- 如果 const 不分配内存,为什么我可以获取 const 的地址?
- 为什么相同的函数签名只有区别,另一个通过 const 获取参数是重新定义?
- 延长函数的寿命延长 由 const& 获取参数并由 const& 返回
- 从本机代码返回"const char*"并在java中获取"字符串"
- 使用const_cast const-ref getter 实现引用获取器的陷阱
- 转换为std :: string并在一行中获取const char *
- 无序地图 - 使用const键获取值
- 获取const lvalue参考的地址是合法的吗?
- 使用 Visual Studio 2013 直接从 std::ostringstream 获取 const char *
- 如何从"const int i"获取i的真实地址
- 如何在不复制或查找的情况下获取 const 字符串流缓冲区的长度?
- 如何在cocos2dx中获取静态const int三维数组长度
- 如何获取对象的const引用并使用该引用更改对象(使用const_cast)
- 如何获取boost::any保存的数据的const引用
- 如何使用用户定义的对象从priority_queue中获取非const顶级元素
- 获取模板类型的基类型(移除const/reference等)
- C++ 为什么 Const& 可以获取 const 值?
- 通过指针获取修饰char*和char const*:很好的实践
- 获取对字符串的子字符串的const访问
- 基于范围的循环:通过值或对const的引用获取项