gpt4 book ai didi

c++ - 通过placement-new手动构造一个平凡的基类

转载 作者:IT老高 更新时间:2023-10-28 23:01:29 29 4
gpt4 key购买 nike

小心,我们正在绕过巨龙的巢穴。

考虑以下两个类:

struct Base {
std::string const *str;
};

struct Foo : Base {
Foo() { std::cout << *str << "\n"; }
};

如您所见,我正在访问一个未初始化的指针。还是我?

假设我只使用 trivialBase 类,只不过是(可能嵌套的)指针包。

static_assert(std::is_trivial<Base>{}, "!");

我想分三步构造Foo:

  1. Foo

  2. 分配原始存储
  3. 通过placement-new初始化一个适当放置的Base子对象

  4. 通过placement-new构造Foo

我的实现如下:

std::unique_ptr<Foo> makeFooWithBase(std::string const &str) {

static_assert(std::is_trivial<Base>{}, "!");

// (1)
auto storage = std::make_unique<
std::aligned_storage_t<sizeof(Foo), alignof(Foo)>
>();

Foo * const object = reinterpret_cast<Foo *>(storage.get());
Base * const base = object;

// (2)
new (base) Base{&str};

// (3)
new (object) Foo();

storage.release();
return std::unique_ptr<Foo>{object};
}

由于 Base 是微不足道的,我的理解是:

  • 跳过在 (2) 构造的 Base 的琐碎析构函数很好;

  • (3) 处构造为 Foo 一部分的 Base 子对象的普通默认构造函数什么都不做;

于是 Foo 收到了一个初始化的指针,一切都很好。

当然,这就是实际发生的情况,即使在 -O3 (see for yourself!) 时也是如此。
但是这样安全吗,还是有一天被龙抢过来吃掉我?

最佳答案

这似乎被标准明确禁止。结束一个对象的生命周期,并开始一个新的对象明确允许在同一位置的生命周期,除非它是一个基类:

§3.8 Object Lifetime

§3.8.7 - If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:

  • the storage for the new object exactly overlays the storage location which the original object occupied, and

  • the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and

  • [snip] and

  • the original object was a most derived object (1.8) of type T and the new object is a most derived object of type T (that is, they are not base class subobjects).

关于c++ - 通过placement-new手动构造一个平凡的基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42947064/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com