让我们考虑一下这个提升文档: http: //www.boost.org/doc/libs/1_35_0/libs/utility/in_place_factories.html
提炼:
struct C
{
template<class InPlaceFactory>
C ( InPlaceFactory const& aFactoty )
:
contained_ ( uninitialized_storage() )
{
aFactory.template apply<X>(contained_);
}
char* uninitialized_storage() { return new char[sizeof(X)] ; }
char* contained_ ;
} ;
实际上,因为 C++ 编译器在初始化列表期间调用类成员构造函数,所以我们不能在没有一些预处理器(或预编译器)的情况下从就地工厂扩展参数。因此,为了避免调用默认构造函数,我们将成员的类型更改为char*
.
我要说的是,这是可悲的。
想象一下这contained_
是预期的类型X
:
有没有办法阻止构造函数被调用?让成员处于未初始化状态,就像它只是一个具有正确空间和类型对齐要求的字节池一样,然后我们可以自由调用我们想要的构造函数,使用placement new
(这正是-place-factory 有)?
这样,我们就不会遇到对齐问题或可读性问题,因为“可以存储什么char*
?随便”
我们可以使用 in-place-factory 表示法,但在一个X
类型上,而不是在一个char*
类型上。
另外,在考虑答案时,请始终牢记您的解决方案应该能够直接在原地工作,如果结构C
在堆栈上实例化,我不想要指针和堆分配,contained_
对象必须保持原地, 在堆栈上。
您注意到原始的 boost 解决方案用于new
受益于 16 字节对齐(在 Microsoft CRT 2014 中大于 4096 的对象减少了 32 字节)。有效地避免了由原本更自然的符号引起的对齐问题:
char contained_[sizeof(X)];
当然,“修复”将是__declspec(align(alignof(X)))
在声明之前使用类似的东西contained_
,但就像我说的那样,使用 char 数组几乎不是一个可维护的解决方案,迫使我们每次想要使用时都强制转换contained_
......
谢谢 !