是否定义了放置新派生类的可简单破坏的基础对象的行为?
struct base { int& ref; };
struct derived : public base {
complicated_object complicated;
derived(int& r, complicated_arg arg) :
base {r}, complicated(arg) {}
};
unique_ptr<derived> rebind_ref(unique_ptr<derived>&& ptr,
int& ref) {
// Change where the `ref` in the `base` subobject of
// derived refers.
return unique_ptr<derived>(static_cast<derived*>(
::new (static_cast<base*>(ptr.release()) base{ref}));
}
请注意,我尝试构建rebind_ref
为了不破坏编译器可能做出的任何严格的别名假设。
不可以,C++ 标准不允许这样做,至少有两个原因。
有时允许将新对象放置到另一个相同类型对象的存储中的文本可以在[基本生活],第 8 段 http://eel.is/c++draft/basic.life#8。粗体强调是我的。
如果一个对象的生命周期结束后,在该对象占用的存储空间被重用或释放之前,在原对象占用的存储位置上创建一个新的对象,一个指向原对象的指针,一个指向该对象的引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,可用于操作新对象,如果:
-
新对象的存储完全覆盖原始对象占用的存储位置,并且
-
新对象与原始对象具有相同的类型(忽略顶级 cv 限定符),并且
-
原始对象的类型不是 const 限定的,并且,如果是类类型,不包含任何类型为的非静态数据成员const 限定或参考类型, and
-
[C++17] 原始对象是最派生对象类型的T
并且新对象是该类型的最派生对象T
(也就是说,他们是不是基类子对象).
-
[C++20 草案 2018-10-09]原始对象和新对象都不是潜在重叠的子对象([介绍.对象])。
C++20 的更改是考虑到零大小非静态数据成员的可能性,但它仍然排除了所有基类子对象(空或非空)。 “潜在重叠子对象”是一个新术语,定义于[介绍对象]第 7 段 http://eel.is/c++draft/intro.object#7:
A 潜在重叠的子对象或者是:
(即使您确实找到了某种方法来重新安排事物以避免引用成员和基类问题,请记住确保没有人可以定义const derived
变量,例如通过将所有构造函数设为私有!)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)