【发布时间】:2018-07-02 08:24:04
【问题描述】:
放置 new 的示例通常使用 unsigned char 数组作为底层存储。步骤可以是:
- 用 new 创建 unsigned char 数组
- 在此存储中创建一个带有新位置的对象
- 使用对象
- 销毁对象
- 为 unsigned char 数组调用 delte 以释放数组
第 5 点似乎只有在我们使用带有微不足道的析构函数的底层存储类型时才有效。否则,我们将调用底层存储类型的析构函数,但其中不存在任何对象。从技术上讲,我们正在破坏一堆不存在的无符号字符,我们很幸运,无符号字符类型的析构函数是微不足道的,所以没有操作。
下面的代码呢:
struct A{ /* some members... */ };
struct B{ /* some members... B shall be same size as A */ };
int main()
{
auto ptr_to_a = new A; // A object lives @ ptr_to_a
ptr_to_a->~A(); // A object destroyed. no object living @ ptr_to_a, but storage is preserved
new (ptr_to_a) B; // B object living @ ptr_to_a.
std::launder(reinterpret_cast<b*>(ptr_to_a))->/*...*/; // use B. for this purpose we need std::launder in C++17 or we would store the pointer returned by the placement new and use it without std::launder
std::launder(reinterpret_cast<b*>(ptr_to_a))->~B(); // B object destroyed. no object living @ ptr_to_a, but storage is preserved
// at this point there is no object living @ ptr_to_a, but we need to hand back the occupied storage.
// a)
delete ptr_to_a; // undefined behavior because no object is sitting @ ptr_to_a
// b)
new (ptr_to_a) A; // create an object again to make behavior defined. but this seems odd.
delete ptr_to_a;
// c)
// some method to just free the memory somehow without invoking destructors?
return 0;
}
https://en.cppreference.com/w/cpp/language/lifetime 上写着: 作为一种特殊情况,可以在 unsigned char 或 std::byte 数组中创建对象(在这种情况下,据说该数组为对象提供存储)如果...。
这是否意味着它只允许在 unsigned char 和 byte 数组上使用放置 new 并且因为它们有一个微不足道的析构函数,所以我的代码示例已经过时?
否则,我的代码示例怎么样?选项 b) 是唯一有效的解决方案吗?
编辑:第二个例子:
struct A{ /* some members... */ };
struct alignas(alignof(A)) B{ /* some members... */ };
int main()
{
static_assert(sizeof(A) == sizeof(B));
A a;
a.~A();
auto b_ptr = new (&a) B;
b_ptr->~B();
return 0;
// undefined behavior because a's destructor gets called but no A object is "alive" (assuming non trivial destructor)
// to make it work, we need to placement new a new A into a?
}
【问题讨论】:
标签: destructor c++17 placement-new