std::vector insert()重新分配

7
我正在查看std::vector代码,发现了一些不太理解的地方。当capacity < size() + 1时,需要重新分配缓冲区以便插入新元素。它所做的事情(根据我从代码中提取出来的)是:
  • 分配新缓冲区
  • 复制旧缓冲区的前缀(0 - 插入索引)
  • 在新缓冲区中构造新元素
  • 复制旧缓冲区的后缀(插入索引 - 结尾)
  • 调用旧缓冲区中所有项目的析构函数
  • 释放旧缓冲区
据我所见,前缀和后缀的复制是通过memmove完成的。memmove是数据的纯二进制复制吗?它不会调用元素的构造函数,对吗?我的疑问是,如果内存只是移动而不是在新缓冲区中重新构造,为什么函数要调用旧缓冲区中元素的析构函数呢?

1
我认为你对代码的理解是错误的。如果你认为使用了memmove,请发一个片段来说明这一点。 - anon
使用memmove是编译器的一种潜在优化。但它只适用于POD类型。如果该类型具有构造函数/析构函数,则需要使用它们。 - Martin York
1个回答

5
我浏览了MSVC8的vector实现,我看不到memmove()。先前的向量元素没有被移动,它们被复制并调用它们的副本构造函数将它们复制到新缓冲区中(该缓冲区在单个分配中分配,使用放置new构造元素)。当然,这只是MSVC实现的情况,但根据标准,这才是vector应该表现出来的行为。
然而,在某些情况下使用memmove是可以的 - 例如对于std :: vector,STL实现可以自由地专门针对此情况进行优化。在阅读源代码时,您可能错过了一个模板“分支”。

是的,我看到了<int>专业化。谢谢! - Flawe
我想知道使用swap(old, new)是否同样有效,而不是构造和析构。 - Zan Lynx
我认为swap不可行,因为它要求oldnew被完全构造,而这在目标缓冲区中并非如此。但是,在C++11中,使用std::move代替std::copy是可以的。 - Alexander Gessler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接