gpt4 book ai didi

c++ - 使用 std::aligned_union 和 std::aligned_union 为小型缓冲区优化别名

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:08:15 26 4
gpt4 key购买 nike

我正在研究 std::function 的小缓冲区优化实现-像对象。

Boost 实现了 boost::function 的小缓冲区像这样:

union function_buffer
{
mutable void* obj_ptr;
struct type_t {
const detail::sp_typeinfo* type;
bool const_qualified;
bool volatile_qualified;
} type;

mutable void (*func_ptr)();

struct bound_memfunc_ptr_t {
void (X::*memfunc_ptr)(int);
void* obj_ptr;
} bound_memfunc_ptr;

struct obj_ref_t {
mutable void* obj_ptr;
bool is_const_qualified;
bool is_volatile_qualified;
} obj_ref;

// To relax aliasing constraints
mutable char data;
};

并做类似的事情:

new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor);

此外,C++11 提供,std::aligned_union std::aligned_storage which seems suitable for this .前者给出了一个类型:

suitable for used as uninitialized storage for any object whose size is at most Len and whose alignment is a divisor of Align

我很想使用类似的东西:

class MyFunction {
private:
typename std::aligned_storage<something>::type buffer;
MyFunctionVtable* vtable;
public:
template<class F>
MyFunction(F f)
{
static_assert(sizeof(F) <= sizeof(buffer) &&
alignof(F) <= alignof(buffer), "Type not suitable");
new (&buffer) F(std::move(f));
vtable = ...;
}
// [...]
};

这(或 boost 实现)是否违反了类型别名规则,为什么?我倾向于认为存在会触发不守卫行为的陷阱。

作为引用,C++ 标准中的注释给出了 aligned_storage 的典型实现。 :

template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
typedef struct {
alignas(Alignment) unsigned char __data[Len];
} type;
};

从某种意义上说,这看起来类似于都​​依赖于 char 的增强版本“启用”别名。

std::aligned_union<>::type呢? ?使用未明确列出的类型是否安全?

最佳答案

大体上,当您使用一种类型写入存储位置并使用另一种类型读取时,会发生别名,并且这些类型都不是窄字符类型(charsigned char , unsigned char ).

如果 Boost 实现在任何时候写入 function_buffer 都是不安全的与一个成员然后阅读另一个成员,除非其中一个成员是 data . data 的事实成员(member)有评论// To relax aliasing constraints可能表明 Boost 开发人员相信他们可以欺骗编译器不注意别名冲突。

您建议的解决方案 std::aligned_storagestd::aligned_union是个好东西,只要你的vtable仅通过写入 placement-new 表达式时使用的类型读取 new (&buffer) F(std::move(f)); , 所以可以写成 reinterpret_cast<F*>(&buffer)并将结果表达式用作 F* 类型的对象指向 F 类型的对象.

std::aligned_union placement-new 任何具有较小尺寸和对齐要求的类型都可以。用 static_assert 明确表示通常是个好主意:

static_assert(sizeof(F) <= sizeof(buffer));
static_assert(alignof(F) <= alignof(buffer));
// OK to proceed
new (&buffer) F(std::move(f));

关于c++ - 使用 std::aligned_union 和 std::aligned_union 为小型缓冲区优化别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38070348/

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