2015-09-24 28 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