为什么这是未定义的行为?
struct s
{
const int id; // <-- const member
s(int id):
id(id)
{}
s& operator =(const s& m) {
return *new(this) s(m); // <-- undefined behavior?
}
};
(引用标准就好了)。
这个问题源于这个答案 https://stackoverflow.com/a/11602256/1729784.
没有什么可以使所示的代码片段本质上是 UB 的。然而,几乎可以肯定的是,在任何正常使用情况下,UB 都会立即跟随。
From [基本生活]/8 http://eel.is/c++draft/basic.life#8(强调我的)
如果一个对象的生命周期结束后,在该对象占用的存储空间被重用或释放之前,在原对象占用的存储位置上创建一个新的对象,一个指向原对象的指针,一个指向该对象的引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,可用于操作新对象,如果:
-
新对象的存储完全覆盖原始对象占用的存储位置,并且
-
新对象与原始对象具有相同的类型(忽略顶级 cv 限定符),并且
-
原始对象的类型不是 const 限定的,并且,如果是类类型,不包含任何类型为 const 限定的非静态数据成员或引用类型,以及
-
原始对象是该类型的最派生对象T
并且新对象是该类型的最派生对象T
(也就是说,它们不是基类子对象)。
由于有一个const
成员于s
,在调用后使用原始变量operator=
将是UB。
s var{42};
var = s{420}; // OK
do_something(var.id); // UB! Reuses s through original name
do_something(std::launder(&var)->id); // OK, this is what launder is used for
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)