在std :: vectors push_back实现中,当size()== capacity()时,它分配两次以上的部分并复制旧的元素,我想问一下,这种复制最有效的方法?
答案 0 :(得分:2)
这在标准中并未真正指定,但留给实施。因此,不同的C ++库版本将以不同方式执行此操作。但是,allocator
的{{1}}必须用于任何分配和取消分配
(因此不使用vector
)。
标准指定的是,如果可以移动(而不是复制)对象,则应移动它们(自C ++ 11起)。通常,将分配一个新的原始内存块,通常是前一个大小的两倍,然后元素从前一个移动(或复制和销毁)。对于一般情况,这种移动/复制必须逐个进行(因为否则,如果没有相应移动/复制构造器的内部的知识,则不能保证移动/复制的完整性)。当然,对于pod(=普通旧数据)类型,可以通过realloc()
进行优化(并且很可能已实现)。
您可以尝试查看您的C ++库实现,但请注意,对于那些不熟悉元模板编程的人来说,代码可能非常不透明:由于各种优化(对于pod,可移动类型等),代码很复杂。 )。
答案 1 :(得分:1)
听起来有点像你想自己实施std::vector<>
最有效的方法是首先避免重新分配,这通常是不可能的。
如果您事先了解下次push_back()
项目的数量,则可以使用std::vector<>::reserve()
并完全避免重新分配。
如果你真的要自己实现,你可能想要使用realloc()
,尽管这是一个可以做的可怕的功能 - 取决于从malloc()
到{free()
的任何参数值{1}}到realloc()
。
为什么这个函数有用的原因是,堆上的数据块后面仍有空间。 realloc()
是唯一一个可以通过扩展此堆块大小来避免100%移动数据的函数,如果有足够的空间来完成,则可以完全不触及数据。
使用realloc()
的缺点是您的特殊表现&#34;实现将放弃分配器的概念以及无法处理需要复制构造函数调用等的元素类型。所以你最好不要命名你的向量向量,而是像&#34; SimpleDataVector&#34;并可能建立一些机制来检测误用。