使用realloc可以安全地重新分配琐碎的可复制对象的存储吗
Can the storage of trivially copyable objects be safely reallocated with realloc?
我知道普通可复制对象可以安全地复制到malloc
的适当存储位置1,并且目标对象将具有与源对象相同的值。
realloc
也可以这样做吗?也就是说,如果realloc
某个存储包含一些类型为T
的对象,而realloc
决定移动和复制块,那么新分配的存储中的对象是否完好无损并已开始其生命周期,旧存储中对象的生命周期是否会安全结束?
1在问这个问题时,我假设"合适的存储位置"包括合适对齐和大小的未初始化存储,但正如M.M下面的回答所说,这实际上并没有得到标准的很好支持。这将使realloc
变得可疑,因为它总是复制到未初始化的存储中。
否,realloc
不能用于安全地移动对象,即使是微不足道的可复制类型,因为realloc
不能在未初始化的存储中创建新对象。
特别是,根据C++14[basic.life]/1:
T类型对象的生存期在以下情况下结束:
如果T是一个具有非平凡析构函数(12.4)的类类型,则析构函数调用启动,或者
对象占用的存储器被重新使用或释放。
调用realloc
会释放或重用存储(我认为即使没有发生重新分配,尽管这对您的问题来说是没有意义的)。因此,对象的生命周期结束。
创建对象的情况包含在[interro.objects]/1:中
通过定义(3.1)和新表达式(5.3.4)创建对象或者在需要时通过实施(12.2)。
这不包括realloc
;因此realloc调用结束了旧对象的生存期,而不创建新对象。
这不仅意味着realloc
不适合复制普通的可复制对象,还意味着使用malloc
或operator new(size_t)
来获得未初始化的存储,然后将memcpy
从现有对象复制到该存储不会创建该对象的可用副本,因为在这种情况下,目标对象也没有被创建。
另请参阅:interpret_cast创建一个普通默认的可构建对象,或使用memcpy构建一个普通可复制对象,以进一步讨论将字节复制到新位置不会在该位置创建对象的事实。
3.8对象生存期很清楚:
T类型对象的生存期从以下时间开始:
1.1获得了具有适当排列和尺寸的T型存储器,并且
1.2如果对象具有非真空初始化,则其初始化完成。
生命周期结束时也是如此。你可以忽略std其他部分的垃圾,比如[interro]!
- 简单可复制与可简单复制
- 如何复制存储在数组中的 STL 对象?
- reinterpret_cast,只读访问,简单的可复制类型,会出什么问题?
- 对于参加可复制和可移动类的访问者来说,应该有多少过载?
- 可变参数宏:无法通过"..."传递非平凡可复制类型的对象
- 为什么 std::atomic<std::string> 会给出微不足道的可复制错误?
- 我可以隐式地创建一个琐碎的可复制类型吗
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 为什么一对常量是微不足道的可复制的,而对不是?
- 在一个微不足道的可复制结构中,移动语义应该实现吗?
- 正在使用放置-new,复制存储,然后访问值未定义的行为
- 防止作用域枚举可复制/可移动
- C :对象上的可复制视图
- 防御性地应用 std::move 到平凡可复制的类型是否不可取
- 为什么 std::function 本身是可复制构造的类型?
- C++不可复制的 lambda 的行为是可复制的
- 错误:无法通过'...'传递非平凡可复制类型的对象'class boost::filesystem::path'
- 不能让类是微不足道的可复制的。我做错了什么?
- 使用临时存储区复制普通的可复制类型:允许吗
- 使用realloc可以安全地重新分配琐碎的可复制对象的存储吗