2014-10-29 48 views
5

我知道那裏很少有C++常見問題解答(以及SO上的答案)表示不需要檢查null的純表達式的返回值,因爲plain new表達通過拋出異常來表示失敗。他們基本上聲明純新的表達式永遠不會返回null。 (通過「簡單的新表達」我的意思是一個新的表達式不是一個nothrow之一)。用戶定義的運算符new返回空指針

然而,儘管這看起來像一個非常基本的問題,但我突然意識到,當他們給出答案時我不明白他們做了什麼具體的假設(如果有的話)。

特別是,我是否允許將基本普通格式::operator new重載爲始終返回空指針,因此希望所有使用該運算符的普通新表達式現在也將返回空指針。

根據語言規範,如果我的::operator new被聲明爲非拋出,那麼我可能會通過返回一個空指針來指示內存分配失敗。所以,讓我們做到這一點

void *operator new(size_t s) throw() { 
    return 0; 
} 

int main() { 
    int *i = new int; 
} 

在我的實驗中,上述新的表達併成功返回一個空指針。那麼,我是否違反了上述代碼中的任何規則?宣佈一個普通的::operator new爲非投擲是否合法?

如果上面的代碼是好的,那麼我會假設當有人聲明一個普通的新「永不返回空指針」時,他們這樣做是假設標準庫提供的版本::operator new還沒有更換。這種推定是否正確?是

+0

這個討論還有另外一個方面 - 即使標準明確允許您按照您說的那樣返回nullptr/0,是處理0的標準庫嗎?我敢打賭他們沒有 - 而實現也沒有 - 所以用':: operator new'編寫一個返回0的程序是不切實際的。 20.8.9.1/4需要'std :: allocate :: allocate'拋出'std :: bad_alloc',如果無法獲得存儲 - 它會(通常冗餘)檢查null還是信任':: operator new'拋出? – 2014-10-29 02:04:48

+0

'new'的非投擲版本是否需要不同的簽名? 'void * operator new(std :: size_t size);'不能返回空指針,即使重新定義它也必須拋出錯誤。 – user657267 2014-10-29 02:09:36

+0

標準庫將使用標準構造的':: new T'和':: new(static_cast (get_allocator()(1))T'來放置,並且這些表單總是調用拋出分配函數(不管是已被替換) – 2014-10-29 02:14:02

回答

1

可以更換運營商如下

[replacement.functions]

(2.1) — operator new(std::size_t) 
(2.2) — operator new(std::size_t, const std::nothrow_t&) 
(2.3) — operator new[](std::size_t) 
(2.4) — operator new[](std::size_t, const std::nothrow_t&) 
(2.5) — operator delete(void*) 
(2.6) — operator delete(void*, const std::nothrow_t&) 

void *operator new(size_t s) throw()是無效的,它在錯誤的情況下

[new.delete扔.single]

void* operator new(std::size_t size); 

3所需行爲:將非空指針返回到適當對齊的 存儲(3.7.4),否則拋出bad_alloc異常。 此要求 對該功能的替換版本具有約束力。

但是,您可以放心地用一個函數,它總是返回null,因爲誰調用這些重載必須意識到這種行爲並相應地檢查返回值替換不拋出noexcept重載。顯然,他們將不會被調用,除非拋出異常標記被傳遞,即int* i = new (std::nothrow) int;

void* operator new(std::size_t size, const std::nothrow_t&) noexcept; 

7要求的行爲:返回一個非空指針對齊適當 存儲(3.7.4),否則返回空指針。這個 的這個notrow版本operator new返回一個從 (可能被替換)的普通版本獲得的指針。該要求對該功能的 替換版本具有約束力。