为什么 vector::迭代器在重新分配时失效
Why is vector::iterator invalidated upon reallocation?
我不明白为什么当重新分配发生时,vector
的迭代器应该失效。
难道不能通过在迭代器中存储偏移量而不是指针来防止这种情况吗?
为什么vector
不是这样设计的?
只是为了引用与性能相关的理由:在设计C++时,Stroustrup 认为像 std::vector 这样的模板类接近本机数组的性能特征至关重要:
强调运行时效率的一个原因...是我想要的 模板在时间和空间上足够高效,可用于 低级类型,如数组和列表。
。
更高级别的替代方案 - 例如,一个带有 size() 的范围检查数组 操作,多维数组,具有正确数字的向量类型 向量运算和复制语义等 -- 将被接受 用户仅当他们的运行时、空间和符号方便时 接近内置数组的那些。
换句话说,提供参数化类型的语言机制 应该使相关用户能够负担得起 消除数组的使用,转而使用标准库类。
Bjarne Stroustrup,C++的设计与演变,第342页。
因为要让迭代器做到这一点,它们需要存储指向矢量对象的指针。 对于每个数据访问,它们需要跟随指向向量的指针,然后跟随其中的指针指向数据数组的当前位置,然后将偏移量 * 元素大小相加。 这会慢得多,并且需要为size_type
成员提供更多内存。
当然,有时这是一个很好的折衷方案,能够在需要时选择它会很好,但它比(C 样式)直接阵列使用更慢、更笨重。 在引入 STL 时,std::vector
的性能受到了无情的审查,并且正常实现针对空间和速度进行了优化,超过了这个便利性/可靠性因素,就像阵列等效operator[]
与阵列一样快,但不如at()
安全。
您可以通过包装标准std::vector<T>::iterator
来增加安全性,但不能通过包装extension::vector<T>::safe_iterator
来增加速度。这是一个一般原则,并解释了许多C++设计选择。
这些决定有很多原因。正如其他人指出的那样,向量iterator
的最基本实现是指向元素的普通指针。为了能够处理push_back
迭代器必须修改以处理进入向量的指针和位置,在通过运算符访问时,向量指针将被取消引用,指向获得数据的指针和添加的位置,并带有额外的取消引用。
虽然这不是最有效的实施方式,但这并不是一个真正的限制因素。VS/Dinkumware 库中迭代器的默认实现(即使在发布中)是经过检查的迭代器,它们管理等量的信息。
实际问题来自其他突变操作。考虑在矢量中间插入/擦除。为了保持所有迭代器的有效性,容器必须跟踪迭代器的所有实例并调整位置字段,以便它们仍然引用相同的元素(已入/删除所取代)。
您需要存储偏移量和指向矢量对象本身的指针。
如指定的那样,迭代器可以只是一个指针,占用的空间更少。
TL;DR -- 因为你正在用简单的无效规则换取更复杂的远距离操作规则。
请注意,"存储指向矢量对象的指针"会导致新的无效情况。 例如,今天swap
保留迭代器有效性,如果指向向量的指针(或引用)存储在迭代器中,则不再可以。 所有移动矢量元数据本身的操作(矢量的矢量吗?)都会使迭代器无效。
您的交易是"当对元素的指针/引用无效时迭代器变得无效",因为"当对向量的指针/引用无效时迭代器变得无效"。
性能参数并不重要,因为提议的替代实现甚至不正确。
我一个迭代器没有失效,它应该指向相同的元素还是指向插入后的相同位置?换句话说,即使没有性能问题,决定使用哪个替代定义也并非易事。
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 我在二维向量中是否正确分配了内存
- 正在尝试重载二进制搜索树分配运算符
- GlobalAlloc而不是其他分配方法
- 自定义先决条件对移动分配运算符有效吗
- 我可以重新分配/覆盖std::字符串吗
- 在c++中使用动态分配的问题
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 为什么我可以使用比分配的内存更多的内存
- 为什么 vector::迭代器在重新分配时失效