在std :: aligned_storage中放置新的?

时间:2015-01-28 08:33:02

标签: c++ c++14

假设我有一个类型模板参数T.

假设我有std::aligned_storage如下:

typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;

我想将新的T放入storage

要传递给贴牌新操作符的符合标准的指针值/类型是什么?如何从storage派生出来?

new (& ???) T(a,b,c);

例如:

new (&storage) T(a,b,c);
new (static_cast<void*>(&storage)) T(a,b,c);
new (reinterpret_cast<T*>(&storage)) T(a,b,c);
new (static_cast<T*>(static_cast<void*>(&storage));

上述哪一项(如果有的话)是合规的,如果没有,那么更好的方法是什么?

2 个答案:

答案 0 :(得分:44)

最偏执的方式是

::new ((void *)::std::addressof(storage)) T(a, b, c);

说明:

  • ::std::addressof防范operator&上的重载一元storage,这在标准上是技术上允许的。 (虽然没有理智的实现会这样做。)::std防范任何可能在范围内的名为std的非顶级名称空间(或类)。
  • (void *)(在这种情况下相当于static_cast)确保您调用展示位置operator newvoid *而不是decltype(storage) * }}。
  • ::new会跳过任何特定于课程的展示位置operator new,以确保通话能够转到全球展示位置。

这样可以保证调用将operator new放置到void *的{​​{1}},T的位置storage。{/ p} >

在大多数理智的程序中,

new (&storage) T(a,b,c);

应该足够了。

答案 1 :(得分:4)

放置分配功能描述如下(C ++ 14 n4140 18.6.1.3):

void* operator new(std::size_t size, void* ptr) noexcept;
     

返回: ptr

     

备注:故意不执行任何其他操作。

20.10.7.6表57描述了aligned_storage<Len, Align>因此:

  

成员typedef type   应为适合使用的POD类型   作为任何对象的未初始化存储   其大小最多为 Len   alignment是 Align的除数。

这意味着在您的情况下,&storage适合对齐以保存T类型的对象。因此,在正常情况下 1 ,您列出的调用展示位置new的所有4种方式都是有效且等效的。为简洁起见,我会使用第一个(new (&storage))。


1 T.C.在评论中正确地指出,你的程序在技术上可以使用typename std::aligned_storage<sizeof(T), alignof(T)>::type*来声明分配函数的重载,然后通过重载决策而不是库提供的&#39;放置新的& #39;版本

我认为这至少在99.999%的情况下不太可能,但如果你需要防范这种情况,请使用其中一个强制转换为void*。直接static_cast<void*>(&storage)就足够了。

另外,如果你偏执到这个级别,你应该使用::new而不是new来绕过任何特定于类的分配函数。