删除std :: vector中间的元素仍然是昂贵的可移动类型?

时间:2011-07-02 13:01:27

标签: c++ vector c++11 move-semantics

通常认为删除std::vector中间的元素是昂贵的,因为它需要复制其后的每个元素以填充空洞。

使用C ++ 11,std::vector移动所有元素,这应该非常快(如果仅与副本有关),至少我是这么认为的。当然,它仍然是线性的,当然,它应该比旧版本更快。

这是真的吗?我不必担心在中间删除一些物体吗?

5 个答案:

答案 0 :(得分:15)

这取决于向量中的内容。如果它是POD或指针,我无法想象它会有任何区别。如果它的类实例很难复制,但可以非常快地移动,我希望用C ++ 0x加速。

但是,我认为如果从std :: vectors中间删除元素是代码中的瓶颈,那么C ++ 0x可能不是正确的修复方法。考虑更好地处理此类情况的数据结构,或std::iter_swapstd::vector::pop_back,如果元素的顺序无关紧要。

答案 1 :(得分:11)

如果考虑到标准用于成本的内容,那将是非常昂贵的。标准规定了对包含类型执行的操作的成本,并且操作数量仍然相同,只是每个操作都会更快。

例如,在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是新旧分配区域中的向量,有效地实现了 move 语义。

答案 2 :(得分:6)

实际上,在绝大多数情况下,移动要比复制快得多。任何具有通过引用存储的信息的类型都可以防止复制 - 例如,几乎所有容器,智能指针等,以及任何涉及这些类型的类。

当然这仍然是线性时间,所以如果你有一百万个整数,它就不会更快。但是,移动诸如容器和智能指针之类的东西比复制它们快几个数量级。

答案 3 :(得分:5)

我仍然是C ++ 0x移动内容的新手,但我无法真正看到你如何获得vector所固有的任何有用的加速。

它必须归结为你的元素类型:我无法想象你会获得任何加速,除非你的元素类型的对象移动比复制更快。

答案 4 :(得分:1)

第一点,即将决定你需要一个矢量或列表?如果您不希望基于索引访问数据结构,则列表将很好,因为您的删除发生在容器的中间。此外,你必须考虑其他变种,如树木,以决定最适合你。这可能不会对您的性能产​​生太大影响,但仍然只是为了共享信息,列表中的内容可能会在多个页面文件中传播,因此在使用大量数据时性能会受到影响。

Rvalue reference and move constructor可以提高容器的性能。它可以避免几次不必要的复制操作等。