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

时间:2013-06-10 20:29:54

标签: c++ for-loop c++11 auto

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

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

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

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

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

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

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

我正在开发一个我正在开发的程序,我正考虑在整个过程中进行此项更改,因为效率至关重要(我之所以在第一时间使用C ++)。

3 个答案:

答案 0 :(得分:65)

是。如果您只读取参数const&

,那么原因相同
T        // I'm copying this
T&       // I'm modifying this
const T& // I'm reading this

这些是你的“默认值”。但是,当T是基本类型(内置)时,您通常只需要恢复为const T(无引用)进行读取,因为副本比别名更便宜。


  

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

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

答案 1 :(得分:1)

免责声明:autoauto&之间的区别通常是微妙的,部分取决于样式,但有时也取决于正确性。我不会在这里介绍一般情况!

在基于循环的范围内,两者之间的区别

for (auto element : container) {}

for (auto& element_ref : container) {}

elementcontainer中元素的副本,而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;    
}

它将打印

23
443
16
49
66
5
5
5
5
5

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

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

答案 2 :(得分:0)

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

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

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