2015-09-24 27 views
1

我正在开发一个不使用异常的项目,并且应该保持这种状态。 为了使用我自己的内存管理器,我重载了(overrid会更准确一些)new操作符。在我的内存管理器中,如果分配失败 - 返回NULL。 现在,虽然新运算符返回NULL,但构造函数正在调用,然后我得到一个seg故障,因为我没有分配内存。 我想要的功能是,如果新的操作符返回NULL,那么不应该调用构造函数(并且之后我会检查对象是否成功初始化)。运算符新重载C++,无例外地处理故障

我希望它的工作是这样的:

myObject = new object(...); 
if (NULL == myObject) 
    printf("error") 
else 
    do something 

谢谢!

+0

的['操作者new'和'操作者新的[]'功能](http://en.cppreference.com/w/cpp/memory/new/operator_new )只分配内存,当你使用'new'运算符时,它是编译器创建代码以调用可能的构造函数。返回一个空指针('nullptr'或者''0)是失败时的正确行为。 –

+0

新对象(...)分配内存并调用构造函数。我只想在分配成功时调用构造函数。我知道这是我所需要的nothrow选项,但是如何在超载时做出这样的事情? – user3445972

+0

@JoachimPileborg只有当你通过'noexcept'或'throw()'声明你的分配函数为非抛出时,请参阅[basic.stc.dynamic.allocation] p3 - 当我禁用异常时,我不清楚这是否是暗示的。 – dyp

回答

7

您需要调用new (nothrow),这样的事情:

myObject* = new (std::nothrow) myObject(...); 

然后,而不是重写规则operator new你需要重写采取std::nothrow_t的一个(或多个)。对于更多的,请看这里:http://www.cplusplus.com/reference/new/nothrow/

经常operator new没有nothrow不应该失败时返回null,而应该抛出。由于您不允许投掷,因此您不能执行这些运算符(除非通过在失败或类似情况下调用abort())。

最后,它可能有助于在编译期间完全禁用异常。我希望这种错误会被捕获(我对此不确定)。

+1

这不是唯一的方法,特别是如果你正在编写自己的'operator new'。 [basic.stc.dynamic。分配] p3 *“如果具有非抛出异常规范的分配函数未能分配存储空间,则它应该返回一个空指针。任何其他分配函数未能分配存储空间,只能通过抛出异常类型将匹配'std :: bad_alloc'类型的处理程序。“* – dyp

+0

@dyp:”具有非抛出异常规范的分配函数“与使用'std :: nothrow_t'的'operator new'不同吗?在我看来,'nothrow'是'noexcept',而'regular'是'noth',所以我不完全确定你在驾驶什么。 –

+1

'std :: nothrow_t'不是一个异常规范。另外,我在引语中删除了一个引用:在*“非抛出异常speficiation”之后*,[basic.stc.dynamic.allocation] p3引用[except.spec],这是关于“异常规格”的部分。虽然你不能用'noexcept'替换默认的'operator new(size_t)',你可以为'noexcept'类类型编写自定义分配函数。 – dyp

0

你将不得不手动做这个,也就是说。

object * create_object(MemoryManager & mem, ...) { 
    void * chunk = mem.get_memory_for_object(); 
    if (chunk == NULL) return NULL; 
    return new (chunk) object(...); // inplace new 
} 
1

最终解决的办法是在new的函数删除结尾添加'throw()'。

void* operator new (size_t size) throw() 

可以在正常的新的或新的(nothrow)中完成。在我的imlpementation中,将它添加到常规new会导致期望的效果,即任何'new'调用在失败时都能够返回NULL。

还有一个在编译中使用'--force_new_nothrow'标志的选项。

约既

更可以发现 here