gpt4 book ai didi

c++ - 在封闭对象的生命周期内通过 placement new 重用数据成员存储

转载 作者:行者123 更新时间:2023-12-01 14:29:29 25 4
gpt4 key购买 nike

这是我的 previous question 的后续我似乎使问题比我原先预期的要复杂得多。 (请参阅问题中的讨论并在那里回答评论。)这个问题是对原始问题的轻微修改,删除了封闭对象构造/销毁期间的特殊规则问题。


是否允许在其封闭对象的生命周期内重用非静态数据成员的存储?如果允许,在什么条件下?

考虑程序

#include<new>
#include<type_traits>

using T = /*some type*/;
using U = /*some type*/;

static_assert(std::is_object_v<T>);
static_assert(std::is_object_v<U>);
static_assert(sizeof(U) <= sizeof(T));
static_assert(alignof(U) <= alignof(T));

struct A {
T t /*initializer*/;
U* u;

void construct() {
t.~T();
u = ::new(static_cast<void*>(&t)) U /*initializer*/;
}

void destruct() {
u->~U();
::new(static_cast<void*>(&t)) T /*initializer*/;
}

A() = default;
A(const A&) = delete;
A(A&&) = delete;
A& operator=(const A&) = delete;
A& operator=(A&&) = delete;
};

int main() {
auto a = new A;
a->construct();
*(a->u) = /*some assignment*/;
a->destruct(); /*optional*/
delete a; /*optional*/

A b; /*alternative*/
b.construct(); /*alternative*/
*(b.u) = /*some assignment*/; /*alternative*/
b.destruct(); /*alternative*/
}

除了 static_assert 之外,还假定 TU 的初始化器、析构器和赋值不会抛出。

对象类型 TU 还需要满足什么条件,以便程序具有已定义的行为(如果有)?

它是否取决于实际调用的 A 的析构函数(例如,/*optional*/ 还是 /*alternative*/ 线条存在)?

是否取决于A的存储时长,例如是否使用 main 中的 /*alternative*/ 行代替?


请注意,除析构函数和destruct 函数外,程序不会在placement-new 之后使用t 成员。当然,当它的存储被不同类型占用时使用它是不允许的。

另请注意,由于我不允许 TU<,程序在所有执行路径中调用其析构函数之前在 t 中构造了一个原始类型的对象 抛出异常。


另请注意,我不鼓励任何人编写那样的代码。我的目的是更好地理解语言的细节。特别是,至少只要不调用析构函数,我就没有发现任何禁止此类放置新闻的内容。

最佳答案

如果 a 被销毁(无论是通过 delete 还是超出范围),然后 t.~T() 被调用,这是 UB,如果 t 实际上不是 T(通过不调用 destruct)。

这不适用于

destruct 被调用后,如果 Tconst 或引用成员 (直到 C++20)。

除此之外,据我所知,您对类(class)的操作没有任何限制。

关于c++ - 在封闭对象的生命周期内通过 placement new 重用数据成员存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59239085/

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