【问题标题】:About iterator of containers关于容器的迭代器
【发布时间】:2021-10-16 10:20:01
【问题描述】:

不知道,为什么会输出1024

vector<int> default_container = { 1,2,3,4,5,6,7,78,8,1024 };
cout << *default_container.end() << endl; // 0
default_container.pop_back();

for (auto it : default_container) 
{
    cout << it << ",";
}
cout << endl;

cout << *default_container.end() << endl;   // 1024 why?why?why?why?
cout << *--default_container.end() << endl; // 8

【问题讨论】:

    标签: c++ c++11 iterator stdvector dereference


    【解决方案1】:

    您的程序有Undefined behavior

    您在行中取消引用结束迭代器

    cout << *default_container.end() << endl;
    ...
    cout << *default_container.end() << endl;
    

    这会给你未定义的行为。形成 cppreference.com std::vector::end, std::vector::cend

    返回指向向量最后一个元素之后的元素的迭代器。 此元素充当占位符;尝试访问它会导致未定义的行为。

    意思是,任何事情都可能发生;因此,您不应该转发它的结果,也不应该这样做!


    话虽如此,您似乎想要访问向量中的最后一个元素。如果是这种情况,对于非空向量,您还有多种其他(安全)选择:

    1. 使用std::vector::back

      // prints first 8 from last; due to "default_container.pop_back()"  
      std::cout << default_container.back(); 
      
    2. 使用std::prev

      #include <iterator>
      
      // prints first 8 from last; due to "default_container.pop_back()"  
      std::cout << *std::prev(default_container.end()); 
      
    3. 使用反向迭代器std::rbegin

      // prints first 8 from last; due to "default_container.pop_back()"  
      std::cout << *std::rbegin(default_container);
      

    附带说明,请参阅:Why is "using namespace std;" considered bad practice?

    【讨论】:

    • @littleZ 然后从行为世界有个好的开始;)
    • 您可能想提一下,您的方法都假定一个非空向量,并且对于空容器具有未定义的行为。
    • @Peter 感谢您的指出。我只关注 OP 的案例,它是非空的。可能对未来的读者有所帮助!
    • *std::prev(default_container.end()); 中,我认为 std:: 由于 ADL 而只是可选的。与std::rbegin 相同。
    • @mediocrevegetable1 但也没有任何问题(开始明确)。
    【解决方案2】:

    前面的答案说明了一切。 换句话说,您不应该将 end() 用于其他任何东西,然后将迭代器与之进行比较。 例如。

    for (auto it = container.begin(); it < container.end(); ++it)
    

    还请注意您的 (auto it : default_container) 行 不是创建迭代器,而是创建一个 int。

    // foreach value in container
    for(int value : default_container) 
    {
      cout << value;
    }
    

    请注意,如果您不打算更改要迭代的值,则可以使用:

    for(const auto value : default_container) {}
    

    或者如果您的容器包含对象(类的实例)

    for(const auto& object : container) {}
    

    【讨论】:

      猜你喜欢
      • 2011-01-15
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 2011-08-28
      • 2015-12-10
      • 2016-01-16
      • 2018-08-01
      • 1970-01-01
      相关资源
      最近更新 更多