【问题标题】:Use the auto keyword in C++ STL在 C++ STL 中使用 auto 关键字
【发布时间】:2011-03-26 22:38:33
【问题描述】:

我见过使用矢量的代码,

vector<int>s;
s.push_back(11);
s.push_back(22);
s.push_back(33);
s.push_back(55);
for (vector<int>::iterator it = s.begin(); it!=s.end(); it++) {
    cout << *it << endl;
}

同理

for (auto it = s.begin(); it != s.end(); it++) {
    cout << *it << endl;
}

在这种情况下使用 auto 关键字有多安全?如果向量的类型是float 呢? string?

【问题讨论】:

    标签: c++ stl c++11


    【解决方案1】:

    auto 关键字从 = 右侧的表达式中获取类型。因此它适用于任何类型,唯一的要求是在声明它时初始化自动变量,以便编译器可以推断出类型。

    例子:

    auto a = 0.0f;  // a is float
    auto b = std::vector<int>();  // b is std::vector<int>()
    
    MyType foo()  { return MyType(); }
    
    auto c = foo();  // c is MyType
    

    【讨论】:

    • 虽然技术上是正确的。我希望这成为不好的做法。如果每个人都只声明他们所有的变量auto,那么人类将变得难以阅读和理解(我们将走向无类型语言的道路)。 auto 的使用应该保留在我们实际上并不关心类型的情况下,只要它在我们想要的庄园中表现即可(例如迭代器,只要我们能,我们实际上并不关心我们得到什么迭代器像迭代器一样使用它)。
    • @Martin:不开玩笑,我第一次看到auto 变量块时,我想“请快点死”。就像你说的,它应该用在那种“给我一个变量,不管它是什么类型”的情况下,而不是“声明一个变量,然后从它的初始化器中推断出它的类型,呵呵呵呵!”试图成为棘手的废话。
    • @sverkerw:不。我的意思是人类很难阅读。 c的类型是什么?我需要知道吗。它如何影响我对其余代码的解释。
    • @LokiAstari:这个问题完全可以通过拥有一个体面的 IDE 来解决,它可以在您将鼠标悬停在“自动”上时告诉您类型。它不是无类型的——它是静态类型的,带有(非常非常简单的)推理。
    • 实际上它似乎已成为标准,并且在大多数情况下使用 auto 会更好。 youtube.com/watch?v=xnqTKD8uD64
    【解决方案2】:

    auto 关键字打算在这种情况下使用,绝对安全。但不幸的是,它仅在 C++0x 中可用,因此您会遇到可移植性问题。

    【讨论】:

      【解决方案3】:

      auto 关键字只是要求编译器从初始化中推断出变量的类型。

      即使是 C++0x 之前的编译器也知道(初始化)表达式的类型,而且您通常可以在错误消息中看到该类型。

      #include <vector>
      #include <iostream>
      using namespace std;
      
      int main()
      {
          vector<int>s;
          s.push_back(11);
          s.push_back(22);
          s.push_back(33);
          s.push_back(55);
          for (int it=s.begin();it!=s.end();it++){
              cout<<*it<<endl;
          }
      }
      
      Line 12: error: cannot convert '__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*, __gnu_norm::vector<int, std::allocator<int> > >, __gnu_debug_def::vector<int, std::allocator<int> > >' to 'int' in initialization
      

      auto 关键字只是让您可以利用这些知识 - 如果您(编译器)知道正确的类型,只需为我选择!

      【讨论】:

      • 对于 STL 工作,汽车已经在我身上成长了。例如,当您想要测试 STL 函数的返回值并且该返回是一对或一些晦涩的东西时,这非常有用。有人知道 GCC 上的编译器标志需要打开其对 auto 的支持吗?
      【解决方案4】:

      这是附加信息,不是答案。

      在 C++11 中你可以这样写:

      for (auto& it : s) {
          cout << it << endl;
      }
      

      而不是

      for (auto it = s.begin(); it != s.end(); it++) {
          cout << *it << endl;
      }
      

      意思相同。

      更新还可以查看@Alnitak 的评论。

      【讨论】:

      • 这些不等价 - 首先变量 itvalue_type 类型,实际上不是迭代器。
      • 在这种情况下,我会将std::endl 替换为"\n",以防止刷新操作。 motivation
      • '\n' 这样你就不需要每次都浪费strlens
      【解决方案5】:

      这是语言中的新项目,我认为我们将在未来几年努力应对。一开始的“自动”不仅存在可读性问题,从现在开始,当您遇到它时,您将不得不花费大量时间来弄清楚它是什么(就像实习生将所有变量命名为xyz :)),但是在容易兴奋的程序员之后,您也会花费大量时间进行清理,例如在我之前回答的曾经。 上面的例子,我可以赌1000美元,会写成 “for (auto it : s)”,而不是“for (auto& it : s)”,因此会在您期望它的列表中调用移动语义,从而修改下面的集合。

      问题的另一个例子是您的问题本身。您显然对 stl 迭代器了解不多,并且您试图通过使用“自动”的魔力来克服这一差距,结果您创建的代码稍后可能会出现问题

      【讨论】:

        【解决方案6】:

        如果您想要一个所有程序员(c++、java 和其他)都可读的代码,请使用原始的旧形式而不是加密的新功能

        atp::ta::DataDrawArrayInfo* ddai;
        for(size_t i = 0; i < m_dataDraw->m_dataDrawArrayInfoList.size(); i++) {
            ddai = m_dataDraw->m_dataDrawArrayInfoList[i];
            //...
        }
        

        【讨论】:

        • “神秘的新功能” 迭代器已经存在了 20 多年。而auto 8 岁了。 ://
        • 此外,基于 C++ 范围的循环非常类似于 Java 的 for 循环,因此使用这种结构实际上提高了 Java 开发人员的可读性。
        猜你喜欢
        • 2018-09-27
        • 1970-01-01
        • 2013-01-11
        • 1970-01-01
        • 2017-02-16
        • 2011-06-08
        • 2011-02-20
        • 2019-11-23
        • 2010-11-05
        相关资源
        最近更新 更多