[英]memset of allocated memory after std::vector::reserve
这里已经有一个与此主题密切相关的问题,但是这个问题引起了激烈的争论,相关的讨论让我有点困惑。 那么下面的想法正确吗?
我的情况如下:我有一个使用块来存储数据的数据结构。 我想使用std::vector<ChunkT> myChunks; myChunks.reserve(1000000);
std::vector<ChunkT> myChunks; myChunks.reserve(1000000);
并在需要时使用ChunkT* newChunk = &myChunks.emplace_back();
. 我希望将新块初始化为零,但我更喜欢在保留 memory 之后直接使用memset
进行此初始化,而不是在我获取它时一次初始化一个块。 前提是ChunkT
是 POD,例如struct {size_t keys[512]; size_t values[512];};
struct {size_t keys[512]; size_t values[512];};
我不确定以下内容:
reserve
后使用memset
对 memory 进行 0 初始化是否安全?struct {size_t keys[512]; size_t values[512];};
struct {size_t keys[512]; size_t values[512];};
在使用ChunkT* newChunk &myChunks.emplace_back()
获取我的块之后? 关于 1.) 链接问题中的用户认为这将是不安全的,因为该标准不保证std::vector
实现可能对保留的 memory 执行什么操作(例如,将其用于内部簿记)。 wpzdm认为,保留的 memory 不会发生任何令人惊讶的事情。 阅读所有相关讨论,我现在认为仅在保留的 memory 中访问对象是安全的,因为它们的生命周期已经开始(因为它们是 POD 并由向量的分配器分配),因此它们是完全有效的对象。 但是,在 memory 成为“有效”范围的一部分之前,它们的内容在任何时候都不能保证,例如通过emplace_back
,因为标准没有说向量实现不能修改保留范围(所以 2.)是否?)。 但是向量实现也不能依赖于那些保留的 object 的内容,因为我们可以在我们认为合适的时候访问和更改它们。 因此,“内部簿记”或设置调试标志以检测“有效”之外但在保留范围内或类似范围内的越界访问都不会严格符合标准,因为它可能导致不允许的副作用。 那么只有恶意或不符合标准的编译器会修改保留范围?
如果我将ChunkT
更改为struct {size_t keys[512]={0}; size_t values[512]={0};};
struct {size_t keys[512]={0}; size_t values[512]={0};};
那么 emplace_back 之后的emplace_back
的内容是有保证的,但这一次是因为初始化是通过构造进行的。 此外,现在访问唯一保留的 memory 将是未定义的行为,因为对象的生命周期尚未开始。
- 是否保证在 ChunkT 为 struct {size_t keys[512]; size_t 值[512];}; 在使用 ChunkT* newChunk &myChunks.emplace_back() 获取我的块之后?
emplace_back()
值初始化 object,因此无论 memory 在创建 object 之前包含什么内容,都可以保证零初始化。
- 保留后使用 memset 对 memory 进行 0 初始化是否安全?
也许它有效,但你最好不要。 通过[]
访问不存在的元素是 UB。
- 是否保证在 ChunkT 为 struct {size_t keys[512]; size_t 值[512];}; 在使用 ChunkT* newChunk &myChunks.emplace_back() 获取我的块之后?
是的。 在您的情况下, emplace_back()
所做的是通过放置新构造一个Chunk
,并且 POD 类将被零初始化。 参考: POD class 初始化放置新默认初始化?
因此,您不必担心 memset 分配的 memory 为零。 如果我错了,请纠正我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.