对于可移动类型,删除std::向量中间的元素仍然很昂贵吗
Is deleting an element in the middle of a std::vector still expensive with movable types?
通常认为删除std::vector
中间的元素成本高昂,因为它需要在每个元素向下复制以填充孔。
对于C++11,std::vector
将向下移动所有元素,这应该非常快(如果只是与副本相关的话(,至少我认为是这样。当然,它在时间上仍然是线性的,但总的来说,它应该比旧版本更快。
这是真的吗?我再也不用担心删除中间的一些对象了吗?
这取决于向量中的内容。如果它是POD或指针,我无法想象它会有什么不同。如果它的类实例复制起来很重,但移动速度很快,我希望C++0x能加快速度。
然而,我认为,如果从std::vectors中间删除元素是代码中的一个瓶颈,那么C++0x可能不是正确的解决方案。考虑更好地处理此类情况的数据结构,或者如果元素的顺序无关紧要,则考虑std::iter_swap
加std::vector::pop_back
。
如果考虑到标准使用的成本,它的成本也会一样高。该标准规定了对所包含类型执行的操作的成本,并且操作的数量仍然相同,只是每一个操作都会更快。
例如,在C++03中考虑在vector<string>
中间插入元素的成本。标准调用O(N)
,其中N
是矢量的大小,但实际成本是O(N * M)
,其中M
是字符串的大小。在分析容器中的操作成本时忽略M
的原因是它取决于所包含的元素。具有可移动类型的C++0x中的成本将是O(N)
(字符串可以移动到新位置(,但在这两种情况下,公布的复杂性都将是O(N)
。
对于一个简单的反例,如果您认为在C++03中,在向量中间插入是一个昂贵的操作,并且您考虑std::vector<int>
,那么在C++0x中,在矢量中间插入也同样昂贵,在这种情况下没有加速。
还要注意,任何潜在的改进都将取决于您的对象是可移动的(它们不需要是(,并且当前的一些STL实现已经以类似的方式进行了优化(没有语言支持(,例如,Dinkumware实现(我认为就是这个(有一些优化,当std::vector<std::vector<T> >
增长时,它创建新的存储并用空向量初始化(这些向量没有分配的内存,因此成本最小(,然后swap
在旧的和新的分配区域中处理向量,有效地实现了移动语义。
实际上,在绝大多数情况下,移动要比复制快得多。任何具有通过引用存储的信息(否则必须复制(的类型都可以阻止复制——例如,几乎所有的容器、智能指针等,以及任何涉及这些类型的类。
当然,这仍然是线性时间,所以如果你有一百万个整数,它不会走得更快。然而,移动容器和智能指针之类的东西可能比复制它们快几个数量级。
我仍然是C++0x移动技术的新手,但我真的不知道如何在这里获得vector
固有的有用加速。
这一切都取决于你的元素类型:我无法想象你会得到任何加速,除非你的元素类别的对象移动比复制快。
第一点,即将决定您需要一个向量或列表?若您不希望对数据结构进行基于索引的访问,则列表会很好,因为您的删除发生在容器的中间。此外,你还必须考虑其他变体,如树,以决定最适合你的。这可能不会对您的性能产生太大影响,但仍然只是为了共享信息,列表中的内容有可能分布在多个页面文件中,因此使用大量数据会影响性能。
Rvalue引用和move构造函数可以提高容器的性能。它可以避免一些不必要的复制操作等。
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- C++:如何循环通过向量中的整数元素
- 如何在C++向量中奇数元素前面加上值-1,我在使用insert函数时遇到了问题
- 不允许在向量中添加更多元素
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 使用并行参数向量调用元素向量的成员函数
- C++ 查找字符串中存在的元素向量
- 包含 std::threads 的元素向量
- 避免从单一元素向量转换为基元类型
- 对自定义元素向量进行排序时出现意外(至少对我来说)行为
- 如何为对元素(向量和int)配对创建unique_ptr也是unique_ptr
- 元素向量乘法 C++(代码不起作用)
- 时间和空间复杂性在二叉树的每个级别创建元素向量(NON-BST)
- 遍历结构元素向量
- 犰狳C++中的元素向量或矩阵乘法
- 为什么'std::vector<int> b{2};'创建 1 元素向量,而不是 2 元素向量?
- 可移动元素向量的大小调整是否有效?
- 唯一元素向量的c++模板函数
- 获取索引和元素-向量问题
- 定义一个生成元素向量的函数时,正确的方法是什么?