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

Bee*_*ope 8 c++ realloc object-lifetime language-lawyer c++11

我知道可以安全地将简单的可复制对象复制malloc到适当的存储位置1,并且目标对象将具有与源相同的值.

这也可能realloc吗?也就是说,如果realloc某个存储包含某些类型的对象T,并realloc决定移动并复制该块,新分配的存储中的对象是否完整并且已经开始其生命周期,并且旧存储中的对象的生命周期将是安全的结束了?


1在提出这个问题时,我曾假设"适当的存储位置"包括适当对齐和大小的未初始化存储,但正如MM的答案所述,这并不是标准所支持的.这会让人realloc怀疑,因为它总是复制到未初始化的存储中.

M.M*_*M.M 9

,realloc不能用于安全地移动对象,即使是简单的可复制类型,因为realloc无法在未初始化的存储中创建新对象.

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

类型T的对象的生命周期在以下情况下结束:

  • 如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用将启动,或者

  • 对象占用的存储器被重用或释放.

调用realloc版本或重用存储(即使没有重新分配,我也会争辩,尽管这对你的问题没有意义).所以对象的生命周期结束.

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

在需要时,定义(3.1),new-expression(5.3.4)或实现(12.2)创建对象.

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

这不仅意味着realloc不适合复制普通的可复制对象,它还意味着使用mallocoperator new(size_t)获取未初始化的存储,然后memcpy从现有对象进入该存储,不会创建对象的可用副本作为目标对象在这种情况下也没有创建.


另请参阅:reinterpret_cast创建一个简单的可默认构造对象,或者使用memcpy构造一个简单的可复制对象,以进一步讨论将字节复制到新位置不会在该位置创建对象的事实.