我想编写一个自定义分配器,它在对象构造之后调用createHook()
,在对象销毁之前调用对称destroyHook()
。我这样使用我的分配器:
class Object {};
class CustomAllocator { /* ... */ };
boost::shared_ptr<Object> object = boost::allocate_shared<Object> (CustomAllocator ());
虽然allocate_shared<>
在我的分配器上正确调用了allocate()
,但它确实使用了就地new
语句而不是在我的分配器上调用construct()
。
我知道如何通过编写自定义my_allocate_shared()
版本来调整此问题,该版本调用createHook()
并返回带有自定义删除器的shared_ptr<>
实例(后者又调用{ {1}}),但我失去了destroyHook()
优化。
我的编码环境仅限于C ++ 03,因此我不知道C ++ 11上下文中allocate_shared<>
的行为(或应该如何)。
答案 0 :(得分:2)
就std::allocate_shared
而言,您所看到的行为是正确的。引用C ++ 11 [util.smartptr.shared.create]:
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args);
2 效果:分配适合类型为
T
的对象的内存,并在该内存中构造一个对象 通过展示位置新表达式::new (pv) T(std::forward<Args>(args)...)
。模板allocate_shared
使用a
的副本来分配内存。如果抛出异常,则函数具有 没有效果。
由于标准库共享指针支持很大程度上基于Boost实现,我想说Boost行为同样有意义。
正如@KerrekSB在评论中指出的那样,显然有一个标准库active issue 2070。
答案 1 :(得分:1)
§20.8.2.2.6[util.smartptr.shared.create] / p1-2:
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args);
需要:表达式
::new (pv) T(std::forward<Args>(args)...)
,其中pv
的类型为void*
, 指向适合存放T
类型对象的存储空间 形成良好。A
应为分配者(17.6.3.5)。副本A
的构造函数和析构函数不会抛出异常。效果:分配适合类型为
T
的对象的内存,并通过放置新表达式构造该内存中的对象::new (pv) T(std::forward<Args>(args)...)
。模板allocate_shared
使用a
的副本来分配内存。如果 抛出异常,函数无效。
简而言之,std::allocate_shared
直接使用展示位置而不是分配器的construct
。