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

时间:2017-10-19 20:53:52

标签: c++ c++11 language-lawyer realloc object-lifetime

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

realloc也可以吗?也就是说,如果realloc某些存储包含某些类型为T的对象,而realloc决定移动并复制该块,则新分配的存储中的对象是否完整并已启动生命周期,旧存储中对象的生命周期是否会安全地结束?

1 在问这个问题时,我曾假设“适当的存储位置”包括合适的对齐和大小的未初始化存储,但正如下面的M.M's answer认为这实际上不是很好标准支持。这会使realloc有问题,因为它总是复制到未初始化的存储中。

2 个答案:

答案 0 :(得分: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)来获取未初始化的存储,然后是{{ 1}}从现有对象到该存储不会创建对象的可用副本,因为在这种情况下目标对象也未被创建

另请参阅:reinterpret_cast creating a trivially-default-constructible objectconstructing a trivially copyable object with memcpy,以进一步讨论将字节复制到新位置不会在该位置创建对象这一事实。

答案 1 :(得分:-3)

3.8对象生存期很明确:

  

T类对象的生命周期始于:

     

1.1获得具有适当对齐和T型尺寸的存储,并且

     

1.2如果对象具有非空的初始化,则其初始化完成。

与生命的终结相同。你可以忽略std其他部分的垃圾,比如[intro]!