無 Heap 的 Pimpl
Ref: Type-safe Pimpl implementation without overhead
一般 Pimpl 用 std::unique_ptr<Impl>,每個物件都要多一次 heap allocation。
改法:在 header 先給定 Impl 的大小與對齊,物件內放一塊 buffer,建構時用 placement new 把 Impl 建在 buffer 上。
cpp
// foo.h
class Foo {
public:
Foo();
~Foo();
private:
struct Impl;
alignas(8) std::byte storage_[64]; // 需 >= sizeof(Impl)
Impl& impl();
};
// foo.cpp
struct Foo::Impl { /* ... */ };
Foo::Foo() {
static_assert(sizeof(Impl) <= sizeof(storage_));
static_assert(alignof(Impl) <= 8);
new (storage_) Impl();
}
Foo::~Foo() { impl().~Impl(); }
Foo::Impl& Foo::impl() { return *std::launder(reinterpret_cast<Impl*>(storage_)); }- 缺點:
Impl變大就要改 header,失去部分 Pimpl 隔離編譯的好處。 - 大小或許可以交給 CMake 在建置時預先算好再產生 header。