问题历史:
从C++98的STL开始,迭代器使我们能够抽象出具体的数据结构,实现对容器元素的统一访问。随着C++20的发布,增加了标准范围,使得在处理容器时的表达能力和安全性进一步提高。
问题:
不正确使用迭代器可能导致运行时错误:越界访问容器,修改后失效。不同类型的迭代器相互混淆会导致意外行为。手动使用begin()/end()需要纪律性。
解决方案:
使用与容器功能相匹配的迭代器类型(例如,只有vector/deque/array才支持随机访问)。不要存储失效的迭代器。对于现代任务,更常使用标准化的范围和算法。
示例代码:
#include <vector> #include <algorithm> #include <iostream> #include <ranges> int main() { std::vector<int> vec{1, 2, 3, 4, 5}; // 通过迭代器迭代 for (auto it = vec.begin(); it != vec.end(); ++it) { std::cout << *it << " "; } // 通过范围迭代 for (int x : vec | std::ranges::views::filter([](int v){return v % 2 == 0;})) { std::cout << x << " "; } return 0; }
关键特点:
在调用push_back后,std::vector的迭代器会发生什么?
如果在push_back后容器的容量增加(重平衡),所有旧的迭代器和引用将变得无效。在push_back不改变容量的情况下,迭代器保持有效。最好在修改之间不存储迭代器。
随机访问迭代器和双向迭代器有什么不同?
随机访问迭代器支持算术(it + n)和索引访问(it[n]),而双向迭代器仅支持++和--。并非所有STL容器都支持随机访问。
标准算法STL能否与普通指针一起工作?
可以,因为C++中的指针完全符合随机访问迭代器的要求。
在std::list的循环中,开发者在不更新迭代器的情况下直接通过erase方法修改容器,这导致了运行时错误。
优点:
缺点:
在修改容器之前,始终保存下一个迭代器。对于向量使用标准的erase-remove惯用法,或对列表使用list::remove_if。
优点:
缺点: