假设有一个结构,其构造函数没有初始化所有成员变量:
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?
}
作为对另一个答案的补充:
如果有人认为这是“技术上未定义的行为,但对我来说足够安全”的话,请允许我演示结果代码的破坏程度。
如果初始化了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()
。它可以“回收”之前存在的垃圾。
什么都行-
你可以在这里玩这些例子。
这是教科书上未定义的行为。成员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会一直转圈