当前位置: 首页 > 知识库问答 >
问题:

C放置后新Memset

贺善
2023-03-14

假设有一个结构,其构造函数没有初始化所有成员变量

struct Foo {
  int x;
  Foo() {}
}

如果我将某个缓冲区设置为0,在该缓冲区上使用placement new创建一个Foo实例,然后从该实例读取x,这是定义的行为吗?

void bar(void* buf) {
  memset(buf, 0, sizeof(Foo));
  Foo* foo = new(buf) Foo;
  std::cout << foo.x; // Is this undefined behavior?
}

共有2个答案

濮彬
2023-03-14

作为对另一个答案的补充:

如果有人认为这是“技术上未定义的行为,但对我来说足够安全”的话,请允许我演示结果代码的破坏程度。

如果初始化了x

struct Foo {
  int x = 0;
  Foo() {}
};

// slightly simpler bar()
int bar(void* buf) {
  std::memset(buf, 0, sizeof(Foo));
  Foo* foo = new(buf) Foo;
  return foo->x; 
}

带有-O3的g-11产生以下结果:

bar(void*):
        mov     DWORD PTR [rdi], 0   <----- memset(buff, 0, 4) and/or int x = 0 
        xor     eax, eax             <----- Set the return value to 0
        ret

这很好。事实上,它甚至没有显示出人们希望通过就地未初始化构造消除的任何开销。编译器很聪明。

与此相反,当不初始化x时:

struct Foo {
  int x;
  Foo() {}
};
// ... same bar

使用相同的编译器和设置,我们得到:

bar(void*):
        mov     eax, DWORD PTR [rdi] <----- Just dereference buf as the result ?!?
        ret

嗯,它当然更快,但是memset()怎么了?

编译器认为,由于我们将未初始化的int(又称垃圾)放在新memsetted内存的顶部,它甚至不需要首先使用memset()。它可以“回收”之前存在的垃圾。

什么都行-

你可以在这里玩这些例子。

穆劲
2023-03-14

这是教科书上未定义的行为。成员x在构造函数之后未初始化,读取未初始化的变量是未定义的行为。

事实上,这段记忆以前被其他东西填满是无关紧要的。

 类似资料:
  • 这个问题是为了确认我对概念的正确理解,并对使用风格和可能的优化提出专家意见。 我正在努力理解“新安置”,下面是我提出的方案。。。 当我运行这个程序时,我得到以下o/p 我有以下问题。。。 这是一个正确的例子来演示新的布局吗 成员a是动态分配的(没有新位置)。那么为什么obj1的地址相同呢 请指出你看到的任何我可以改进的地方,或者只是不要尝试。欢迎任何好的参考或阅读。

  • 这是流放之路新联盟的开始,你决定创建一个公会,其唯一目的是共享资源并作为一个团队成长。 招募流放者、挖掘者、货币翻转者和工匠。 主宰经济并升级您的公会成员。 注意:本游戏无存档系统,刷新会丢失进度从头开始!

  • 我已将STS更新到3.6.4版。释放当我尝试启动java项目时,我在控制台中收到以下错误消息: Fehler:Hauptklasse Files.springsource.vfabric-tc-server-Developers-2.9.3。发布。base-instance.conf.logging.propertieskonnte nicht gefunden oder geladen werd

  • 我有以下代码打算创建一个数组,但没有对其对象进行默认初始化。我想完美地前进到placement new,这似乎发生了,但我发现对象的析构函数在emplace函数中被调用。 运行该程序的结果如下: 它表明对象被构造一次并被销毁两次(显然是UB),一次在emplace函数中,然后一次在NoInitArray的销毁时。 问题是“为什么Int对象的析构函数在emplace函数中调用?”? 编译器,Wind

  • 我正在使用cdk拖动 现在,这就是我所拥有的: 馅饼的家长 Pie.html 馅饼ts

  • 尝试过添加loop: true、 监听视频播放结束后重新播放等方式都是h5正常,app会一直转圈