C++ 为什么std::vector::insert复杂性是线性的(而不是常数)?

C++ 为什么std::vector::insert复杂性是线性的(而不是常数)?,c++,stl,C++,Stl,假设我在大小为“n”的std::vector中的第I个位置插入了p个新元素 由于std::vector中的项保证为其元素使用连续的存储位置,因此执行上述操作似乎需要4个步骤: 1) 如果我们没有空间,向量可能会重新分配,基本上是它的两倍大小。但这是一个恒定的时间操作(尽管是一个非常大的操作) 2) 接下来是从索引0到i-1的元素从旧向量到新向量的memcpy 3) 然后,您将在第i个索引处复制正在插入的“p”新项 4) 然后为从旧向量到新向量的从i+1到n个索引的所有项创建另一个memcpy 以

假设我在大小为“n”的
std::vector
中的第I个位置插入了p个新元素

由于
std::vector
中的项保证为其元素使用连续的存储位置,因此执行上述操作似乎需要4个步骤:

1) 如果我们没有空间,向量可能会重新分配,基本上是它的两倍大小。但这是一个恒定的时间操作(尽管是一个非常大的操作)

2) 接下来是从索引0到i-1的元素从旧向量到新向量的memcpy

3) 然后,您将在第i个索引处复制正在插入的“p”新项

4) 然后为从旧向量到新向量的从i+1到n个索引的所有项创建另一个memcpy

以上不是所有的固定时间操作吗?那么插入本身不应该是一个恒定时间的操作吗?那么为什么
std::vector::insert
与插入的元素数量(复制/移动构造)加上定位(移动)后的元素数量成线性关系

以上不是所有的固定时间操作吗

否,
memcpy
memmove
的时间复杂度在被复制或移动的块的大小上是线性的,因为被移动的
k
字节中的每一个都需要精确地触摸一次。正在移动的块的大小是
sizeof(T)*N
,这也使得定时线性化


由于在重新分配时复制数据,即使在向量末尾添加元素也具有线性复杂度(但是,将
N
元素添加到向量末尾具有摊销线性复杂度,这转化为每项摊销常数的复杂度).

重新分配的成本应该随着大小的增加而增加。如果底层内存块没有被充分利用,则不需要重新分配,但您应该将n个元素向左移动以插入新的元素。(这是通过
memcpy()
完成的,正如其他人所注意到的,这不是O(1)。
memcpy()
ing 4KB需要与3MB相同的时间?当然不是。)当然不是。
memcpy
的成本与复制的数据量成渐近比例。@user2672165,vector使用这样一种分配策略,即RealLocations的成本是“摊销常数”。摊销常数在这里得到了很好的解释:任何使用memcpy的std::vector实现都有根本性的缺陷。它没有正确调用构造函数/析构函数和赋值运算符。你的意思是,摊销常量复杂性。此外,纠正非平凡复杂类型的OP也是一个不错的选择。