0

让我们考虑一下这个提升文档: 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_......

谢谢 !

4

0 回答 0