C++ 11基于范围的for循环效率"const auto&i"与"auto i"

use*_*561 55 c++ for-loop auto c++11

在C++ 11中,我可以迭代一些容器,如下所示:

for(auto i : vec){
   std::cout << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

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

for(auto &i : vec){
   std::cout << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

但是我想确保它们的值vec永远不会被修改并遵守const-correctness,所以我可以这样做:

for(const auto &i : vec){
   std::cout << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

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

我正在开发一个我正在开发的程序,我正在考虑在整个过程中进行这种改变,因为效率是至关重要的(我在第一时间使用C++的原因).

GMa*_*ckG 70

是.如果您只读取参数的参数,也会出现同样的原因const&.

T        // I'm copying this
T&       // I'm modifying this
const T& // I'm reading this
Run Code Online (Sandbox Code Playgroud)

这些是你的"默认值".但是,如果T是基本类型(内置),通常只需要恢复const T(无引用)进行读取,因为副本比别名便宜.


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

  1. 不要盲目彻底改变.一个工作程序比一个快速但破碎的程序更好.
  2. 如何迭代循环可能不会产生太大的影响; 你是因为某种原因而循环,不是吗?你的循环体更可能是罪魁祸首.
  3. 如果效率至关重要,您希望使用分析器来查找程序的哪些部分实际上很慢,而不是猜测可能很慢的部分.请参阅#2,了解为什么您的猜测可能出错.

  • @SergioMartins:不会,为什么你应该只使用`const T&`.一般来说,这就是你想要的,当你碰巧知道`T`时,将它进一步修改为"`const T`"或只是"`T`"是毫无意义的努力; 编译器会为你做这件事. (2认同)
  • 使用“ const auto&”表示您打算不做任何修改,也不需要复制。即使性能相同,我也会这样做,因为它使您的代码更具表现力。 (2认同)

for*_*818 5

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

在基于范围的 for 循环中,

for (auto element : container) {}
Run Code Online (Sandbox Code Playgroud)

for (auto& element_ref : container) {}
Run Code Online (Sandbox Code Playgroud)

是 中element元素的副本container,而element_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;    
}
Run Code Online (Sandbox Code Playgroud)

它会打印

23
443
16
49
66
5
5
5
5
5
Run Code Online (Sandbox Code Playgroud)

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

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