66

在 C++11 中,我可以像这样迭代一些容器:

for(auto i : vec){
   std::cout << i << std::endl;
}

但我知道这是不必要的 -不必要的,因为我只需要打印-的值就vec可以复制(编辑:每个元素)vec,所以我可以这样做:

for(auto &i : vec){
   std::cout << i << std::endl;
}

但我想确保 的值vec永远不会被修改并遵守 const 正确性,所以我可以这样做:

for(const auto &i : vec){
   std::cout << i << std::endl;
}

所以我的问题是:如果我只需要查看某个容器的值,const auto &i由于没有额外副本(编辑:每个元素)的效率提高,是否总是首选最后一个循环()vec

我有一个正在开发的程序,我正在考虑在整个过程中进行这种更改,因为效率在其中至关重要(我首先使用 C++ 的原因)。

4

3 回答 3

88

是的。同样的原因,如果你只读过一个参数,你就创建了参数const&

T        // I'm copying this
T&       // I'm modifying this
const T& // I'm reading this

这些是您的“默认值”。但是,当T是基本类型(内置)时,您通常只需恢复到const T(无参考)阅读,因为副本比别名便宜。


我有一个正在开发的程序,我正在考虑在整个过程中进行此更改,因为效率在其中至关重要

  1. 不要盲目地进行彻底的改变。一个工作程序比一个快速但损坏的程序要好。
  2. 你如何迭代你的循环可能不会有太大的不同。你循环是有原因的,不是吗?你的循环体更有可能是罪魁祸首。
  3. 如果效率很关键,您希望使用分析器来查找程序的哪些部分实际上很慢,而不是猜测可能很慢的部分。请参阅 #2 了解为什么您的猜测可能是错误的。
于 2013-06-10T20:33:12.790 回答
5

auto免责声明:通常和之间的区别auto&是微妙的,部分是风格问题,但有时也是正确性问题。我不打算在这里介绍一般情况!

在基于范围的 for 循环中,

for (auto element : container) {}

for (auto& element_ref : container) {}

is thatelement是 中元素的副本container,whileelement_ref是对容器中元素的引用。

要查看操作上的差异,请考虑以下示例:

#include <iostream>

int main(void) {
    int a[5] = { 23,443,16,49,66 };

    for (auto i : a) i = 5;       
    for (const auto& i : a) std::cout << i << std::endl;
    for (auto& i : a) i = 5;   
    for (const auto& i : a) std::cout << i << std::endl;    
}

它会打印

23
443
16
49
66
5
5
5
5
5

因为第一个循环作用于数组元素的副本,而第二个循环实际上修改了数组中的元素。

如果您不想修改元素,那么通常 aconst auto&更合适,因为它避免了复制元素(这可能很昂贵)。

于 2019-08-21T07:23:49.753 回答
1

想象一下,如果您的向量包含字符串。长弦。5000 长串。不必要地复制它们,你最终会得到一个写得很好的 for 循环,但效率非常低。

确保您的代码符合您的意图。如果您不需要循环内的副本,请不要制作副本。

使用参考 & 如上所述,或迭代器。

于 2017-10-15T20:10:49.913 回答