【问题标题】:Auto vs concrete type when iterating over vector?迭代向量时自动与具体类型?
【发布时间】:2012-08-18 12:31:59
【问题描述】:

我正在阅读的这本书在迭代 vector 时提供了这个示例

for (auto &e: v) {
  cout << e << endl;
}

假设v被声明为vector&lt;int&gt; v,换句话说,我们知道这个集合中元素的类型是int。

使用auto 是否更好或更喜欢?

for (int &e: v) {
  cout << e << endl;
}

为什么?

【问题讨论】:

    标签: c++ c++11 int auto


    【解决方案1】:

    是的。 auto 是首选。因为如果你把v的声明从:

    std::vector<int> v;  //before 
    

    到这里:

    std::vector<float> v; //after
    

    如果您在for 中使用int &amp;,那么您也必须更改它。但是有了auto,就不用改了!

    在我看来,使用auto 或多或少类似于programming to interface。所以如果你在循环中做了一个操作+=,而你并不真正关心循环变量e的类型,只要类型支持+=操作,那么auto就是解决方案:

    for(auto & e : v)
    {
          e += 2;
    }
    

    在这个例子中,你只关心e 的类型支持+= 和右侧的int。它甚至适用于已定义 operator+=(int) 或 operator+=(T) 的用户定义类型,其中 T 是支持从 int 进行隐式转换的类型。就好像你正在编程接口:

    std::vector<Animal*> animals;
    animals.push_back(new Dog());
    animals.push_back(new Cat());
    animals.push_back(new Horse());
    
    for(size_t i = 0 ; i < animals.size(); ++i)
    {
           animals[i]->eat(food); //program to interface
    }
    

    当然,你想把这个循环写成:

    for(Animal * animal : animals)
    {
           animal->eat(food); //still program to interface
    }
    

    或者简单地说:

    for(auto animal : animals)
    {
           animal->eat(food); //still program to interface
    }
    

    还是programming to interface。

    但与此同时,@David 评论中的观点值得注意。

    【讨论】:

    • 这可以两种方式阅读,最好得到一个编译错误,指出不能从float&amp; 设置int&amp;,而不是编译器静默接受本应使用的代码ints...并不是说拥有int&amp; 是一个更好的主意,这完全取决于您在for 循环的主体中所做的事情,如果它不依赖于确切的类型auto 会更好
    • @DavidRodríguez-dribeas:我认为你所说的情况非常不寻常。通常,我们必须将int 更改为float 在这种情况下auto 是一个更好的解决方案。
    • 同意。在大多数情况下auto&amp; 会做......但我还不习惯没有明确的类型:)(除非我真的不想知道!)
    • 我认为基本面的情况与用户定义的类型相比差异很大。 Fundamentals 有这种被隐式转换为其他人的讨厌习惯,因此 David 的观点在这里非常重要——您可以更改集合类型,您的循环仍然可以编译,但会产生无意义的结果。
    • @edA-qa mort-ora-y:如果我更改集合类型,那么for (int &amp;e: v) 将不会编译。请注意,它是int &amp; e,而不仅仅是int e。但是,for (int e: v) 将编译。
    【解决方案2】:

    在您的第一个示例中,您对向量元素的依赖较少。

    假设在一个月内,您需要向量存储更大的整数,因此您将不得不使用std::vector&lt;int64_t&gt; 或其他更宽的类型。现在,遍历该向量的所有代码均无效。您必须修改每个:

    for (int &e: v) {}
    

    对于一个:

    for (int64_t &e: v) {}
    

    这就是为什么最好让auto 推断内部类型。这样,您可以将存储在向量中的类型修改为另一个兼容的类型,并且您的所有代码仍然可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      相关资源
      最近更新 更多