C++11 make_unique的异常感知malloc版本

C++11 make_unique的异常感知malloc版本,c++11,exception-handling,malloc,unique-ptr,placement-new,C++11,Exception Handling,Malloc,Unique Ptr,Placement New,在C++11中,没有make_unique(不能使用C++14),尽管人们可以很快被模仿成这样(已经有很多答案表明类似于此): 这似乎没问题,但在这里,异常处理完全被忽略了,new(ptr)T(…)如何工作,而不是new T(…),以及这如何影响任何版本的make_unique,尤其是在使用自定义分配方法时 首先,我知道抛出std::bad_alloc是不明智的,但是我相信最小意外的原则适用于这里,并且可以模拟new将要做的事情(即,在分配失败时抛出,而不是返回nullptr)。这就引出了两个问

C++11
中,没有
make_unique
(不能使用
C++14
),尽管人们可以很快被模仿成这样(已经有很多答案表明类似于此):

这似乎没问题,但在这里,异常处理完全被忽略了,
new(ptr)T(…)
如何工作,而不是
new T(…)
,以及这如何影响任何版本的
make_unique
,尤其是在使用自定义分配方法时

首先,我知道抛出
std::bad_alloc
是不明智的,但是我相信最小意外的原则适用于这里,并且可以模拟
new
将要做的事情(即,在分配失败时抛出,而不是返回
nullptr
)。这就引出了两个问题

1。将
返回{nullptr}
替换为
抛出std::bad_alloc()

2。要正确复制新T(…)的行为,如果构造函数抛出异常,则需要捕获异常,以便立即释放内存,然后重新抛出构造函数异常?

假设两者都是,下面是正确处理的情况还是有什么要考虑的?< /P>

template< typename T, typename ... Args >
auto malloc_make_unique_v2 (Args && ... args) -> std::unique_ptr< T, destroy_free< T > > {
  if ( auto ptr = malloc( sizeof(T) ) ) try {
    return { new ( ptr ) T( std::forward< Args >( args )... ) };
  } catch( ... ) { // catch constructor exceptions
    // assumed: memory allocated but object not constructed
    free( ptr ); // release memory, object was not constructed?
    throw; // propagate whatever the exception was during construction?
  }
  throw std::bad_alloc(); // no memory allocated, throw bad_alloc?
}
模板
自动malloc_make_unique_v2(Args&&…Args)->std::unique_ptr>{
如果(auto ptr=malloc(sizeof(T)),请尝试{
返回{new(ptr)T(std::forward(Args)…)};
}catch(…){//catch构造函数异常
//假定:已分配内存,但未构造对象
释放(ptr);//释放内存,对象未构造?
throw;//传播构造期间的异常吗?
}
抛出std::bad_alloc();//没有分配内存,抛出bad_alloc?
}
编辑-请注意,为了简单起见,我忽略了对齐

假设两者都是,下面是正确处理的情况还是有什么要考虑的?< /P>

template< typename T, typename ... Args >
auto malloc_make_unique_v2 (Args && ... args) -> std::unique_ptr< T, destroy_free< T > > {
  if ( auto ptr = malloc( sizeof(T) ) ) try {
    return { new ( ptr ) T( std::forward< Args >( args )... ) };
  } catch( ... ) { // catch constructor exceptions
    // assumed: memory allocated but object not constructed
    free( ptr ); // release memory, object was not constructed?
    throw; // propagate whatever the exception was during construction?
  }
  throw std::bad_alloc(); // no memory allocated, throw bad_alloc?
}
我觉得还可以


有一种方法可以使用自定义分配器分配的对象内存创建共享的_ptr。您所做的基本上是代码> > AlcalTeaION/<代码>,在标准C++中不存在(也许还没有)。也许您可以创建使用malloc/free的自定义分配器,然后实现您自己的分配器(如果您没有),并且
allocate\u unique

函数在出错时是否抛出或返回
nullptr
,这是一个设计决策。但是,抛出一些错误并为其他错误返回
nullptr
(您的第一个版本就是这样做的)的概念会让代码的用户感到困惑/烦恼。
template< typename T, typename ... Args >
auto malloc_make_unique_v2 (Args && ... args) -> std::unique_ptr< T, destroy_free< T > > {
  if ( auto ptr = malloc( sizeof(T) ) ) try {
    return { new ( ptr ) T( std::forward< Args >( args )... ) };
  } catch( ... ) { // catch constructor exceptions
    // assumed: memory allocated but object not constructed
    free( ptr ); // release memory, object was not constructed?
    throw; // propagate whatever the exception was during construction?
  }
  throw std::bad_alloc(); // no memory allocated, throw bad_alloc?
}