Amb*_*jak 7 c++ placement-new undefined-behavior language-lawyer
让S是含有一个字符阵列的结构类型data,其具有的最大对齐和固定大小.这个想法是S能够存储任何类型T的对象,其大小不超过限制,并且可以简单地复制构造并且可以简单地破坏.
static constexpr std::size_t MaxSize = 16;
struct S {
alignas(alignof(std::max_align_t)) char data[MaxSize];
};
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
后来给出了这个S值的副本,reinterpret_cast用于T*从指针获取字符数组的开头,然后T以某种方式访问该对象.的T类型是相同的创建值时.
void access(S s) {
T *t = reinterpret_cast<T *>(s.data);
t->print();
}
Run Code Online (Sandbox Code Playgroud)
我想知道这个方案中是否有任何未定义的行为以及它将如何解决.例如,我担心:
std::launder旨在解决的问题?我不确定data在构造一个实例之后是否可以作为字符数组进行访问T.我需要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;
}
Run Code Online (Sandbox Code Playgroud)
这可能有用。它将编译器对某个位置的数据的解释从一种 Pod 类型转换为另一种类型,并编译为优化下的 noop。
因此,将缓冲区、洗衣盒移至 T,写入数据,洗衣盒返回 gdneric 存储。要读取,请将 pod 清洗到 T。请注意,通过 T 指针进行的所有写入都应将其清洗回通用存储,以避免使用别名规则来优化看似已丢弃的 ptr 上的写入。
| 归档时间: |
|
| 查看次数: |
157 次 |
| 最近记录: |