gpt4 book ai didi

c++ - 是否正在使用 placement-new,复制存储然后访问值未定义行为?

转载 作者:可可西里 更新时间:2023-11-01 18:39:50 26 4
gpt4 key购买 nike

S 是一个结构类型,它包含一个字符数组 data,它具有最大对齐和固定大小。这个想法是 S 能够存储任何类型 T 的对象,其大小不超过限制并且是平凡复制构造和平凡可破坏的。

static constexpr std::size_t MaxSize = 16;
struct S {
alignas(alignof(std::max_align_t)) char data[MaxSize];
};

Placement-new 用于构造一个T 类型的对象到一个新的S 对象的字符数组中。然后该对象被复制任意次数,包括返回和按值传递。

template <typename T>
S wrap(T t) {
static_assert(sizeof(T) <= MaxSize, "");
static_assert(std::is_trivially_copy_constructible_v<T>, "");
static_assert(std::is_trivially_destructible_v<T>, "");

S s;
new(reinterpret_cast<T *>(s.data)) T(t);
return s;
}

稍后给定此 S 值的拷贝,reinterpret_cast 用于从指向字符数组开头的指针获取 T* ,然后以某种方式访问​​ T 对象。 T 类型与创建值时相同。

void access(S s) {
T *t = reinterpret_cast<T *>(s.data);
t->print();
}

我想知道这个方案是否涉及未定义的行为以及如何解决。例如,我担心:

  • “重用对象存储”是否存在问题,即 std::launder 旨在解决的问题?我不确定在那里构造 T 的实例后以字符数组形式访问 data 是否有效。我是否需要在访问值的地方使用 std::launder,为什么?
  • 生成的 S 复制构造函数是否存在问题,它复制了 data 中的所有字节,因为某些字节可能尚未初始化?我担心 sizeof(T) 之外的字节以及 T 对象中可能未初始化的字节(例如填充)。

我的用例是实现一个非常轻量级的多态函数包装器,它可以与满足我为 T 列出的那些要求的任何可调用项一起使用。

最佳答案

template<class T>
T* laundry_pod(void* ptr){
char buff[sizeof(T)];
std::memcpy(buff, ptr, sizeof(T));
auto* r=::new(ptr)T;
std::memcpy(ptr, buff, sizeof(T));
return r;
}

这可能有用。它将编译器对某个位置的数据的解释从一种 pod 类型转换为另一种类型,并在优化下编译为 noop。

所以把你的缓冲区,laundry pod 放到 T,写入它,laundry pod 回到 gdneric storage。要阅读,请将 pod 洗衣到 T。请注意,所有通过 T 指针的写入都应在将其清洗回通用存储之后,以避免使用别名规则来优化看似丢弃的 ptr 上的写入。

关于c++ - 是否正在使用 placement-new,复制存储然后访问值未定义行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49841538/

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