可以使用 realloc 安全地重新分配普通可复制对象的存储吗?

Can the storage of trivially copyable objects be safely reallocated with realloc?

我知道 trivially copyable 对象可以安全地复制我的 malloc 到适当的存储位置1 并且目标对象将具有相同的值作为来源。

realloc也可以这样吗?也就是说,如果 realloc 一些存储包含一些 T 类型的对象,并且 realloc 决定移动和复制该块,那么新分配的存储中的对象是否完好无损并开始了它们的工作?生命周期,旧存储中对象的生命周期是否会安全结束?


1 在问这个问题时,我曾假设 "appropriate storage location" 包含未初始化的适当对齐和大小的存储,但正如下面的 所论证的那样实际上并没有得到标准的很好支持。这会让 realloc 产生疑问,因为它总是复制到未初始化的存储中。

realloc不能用于安全移动对象,即使是普通可复制类型,因为realloc不能在未初始化的存储中创建新对象。

特别是,根据 C++14 [basic.life]/1:

The lifetime of an object of type T ends when:

  • if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or

  • the storage which the object occupies is reused or released.

调用 realloc 释放或重用存储(即使没有发生重新分配,我认为,尽管这对您的问题没有实际意义)。所以对象的生命周期结束了。

创建对象的情况由[intro.objects]/1 涵盖:

An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed.

这不包括realloc;所以 realloc 调用结束了旧对象的生命周期并且不创建新对象。

这不仅意味着 realloc 不适合复制平凡可复制的对象,还意味着使用 mallocoperator new(size_t) 来获取未初始化的存储,然后是memcpy 从现有对象到该存储不会创建该对象的可用副本,因为在这种情况下目标对象也没有被 创建


另请参阅:, or 以进一步讨论将字节复制到新位置不会在该位置创建对象这一事实。

3.8对象生命周期明确:

The lifetime of an object of type T begins when:

1.1 storage with the proper alignment and size for type T is obtained, and

1.2 if the object has non-vacuous initialization, its initialization is complete.

生命周期结束时也是如此。你可以忽略 std 其他部分的垃圾,比如 [intro]!