Does std::vector *have* to move objects when growing capacity? Or, can allocators “reallocate”?

后端 未结 3 1500
广开言路
广开言路 2020-11-27 04:33

A different question inspired the following thought:

Does std::vector have to move all the elements when it increases its capacity?

相关标签:
3条回答
  • 2020-11-27 04:58

    Yep, you're right that the standard allocator interface doesn't provide optimizations for memcpy'able types.

    It's been possible to determine whether a type can be memcpy'd using boost type traits library (not sure if they provide it out of the box or one would have to build a composite type discriminator based on the boost ones).

    Anyway, to take advantage of realloc() one would probably create a new container type that can explicitly take advantage of this optimization. With current standard allocator interface it doesn't seem to be possible.

    0 讨论(0)
  • 2020-11-27 04:59

    In most cases, realloc will not extend the memory, but rather allocate a separate block and move the contents. That was considered when defining C++ in the first place, and it was decided that the current interface is simpler and not less efficient in the common case.

    In real life, there are actually few cases where reallocis able to grow. In any implementation where malloc has different pool sizes, chances are that the new size (remember that vector sizes must grow geometrically) will fall in a different pool. Even in the case of large chunks that are not allocated from any memory pool, it will only be able to grow if the virtual addresses of the larger size are free.

    Note that while realloc can sometimes grow the memory without moving, but by the time realloc completes it might have already moved (bitwise move) the memory, and that binary move will cause undefined behavior for all non-POD types. I don't know of any allocator implementation (POSIX, *NIX, Windows) where you can ask the system whether it will be able to grow, but that would fail if it requires moving.

    0 讨论(0)
  • 2020-11-27 05:02

    When std::vector<T> runs out of capacity it has to allocate a new block. You have correctly covered the reasons.

    IMO it would make sense to augment the allocator interface. Two of us tried to for C++11 and we were unable to gain support for it: [1] [2]

    I became convinced that in order to make this work, an additional C-level API would be needed. I failed in gaining support for that as well: [3]

    0 讨论(0)
提交回复
热议问题