2015-11-24 24 views
4

的幾個問題已經被問過的計算器這個問題,但我還沒有看到任何解釋理由 delete表達式的限制落後。
爲了澄清這個問題,我試圖收集事實,因爲我已經在接下來的三個評論中理解了這些事實。爲什麼我們可以將可選參數傳遞給新表達式,而不是刪除表達式?

備註1:一般新的表達
讓我們考慮任何「運營商新的」(不管它是默認的全球性的,它覆蓋默認的全局之一,重載版本或類成員一個版本版)。我們假設我們也有一個匹配的「操作員刪除」。 假設原型如下:

void* operator new(size_t, T1, T2, ..., Tn); 
void operator delete(void*, T1, T2, ..., Tn); 

我們知道,當程序員類型的一種新的表達:

T* t = new(t1, ..., tn) T(); 

(其中T1類型的,......,分別是TN T1, ... TN)
編譯器自動替換這一行的東西,如:

T* t; 
void* raw = operator new(sizeof(T), t1, ..., tn); // or T::operator new(...) 
try { 
    t = new(raw) T(); 
} 
catch (...) { 
    operator delete(raw, t1, ..., tn); // or T::operator delete(...) 
    throw; 
} 

注2:刪除的表達 - 在某些情況下,法律
我們知道,當程序員類型此刪除表達式:

delete t; 

(其中t的類型是T)
編譯器會自動替換該行類似於:

if (t) { 
    t->~T(); 
    operator delete(t); // or T::operator delete(t); 
} 

因此,我們知道用簡單的語法「delete t;」我們可以隱式並自動調用任何「delete操作符」是採用相同的參數作爲默認的全局一個(也可以是默認的全球性的本身,即覆蓋默認的全局的一個版本,或採取一類成員版本與默認的全局參數相同的參數)。

注3:刪除的表達 - 一般非法
讓我們考慮任何「delete操作符」是不採取相同的參數作爲默認的全球性(也可以是一個全球性的重載版本或類成員版本)。 假設原型如下:

void operator delete(void*, T1, ..., Tn); 

我們本來寫的一般刪除表達式:

delete(t1, ..., tn) t; 

希望編譯器會自動將其替換爲:

if (t) { 
    t->~T(); 
    operator delete(t, t1, ..., tn); // or T::operator delete(...); 
} 

...,不幸的是我們知道「delete(t1,...,tn)t;」是非法的

因此,通常建議編寫模板功能,如:

template<typename T> void destroy(T* t, T1 t1, ..., Tn tn) { 
    if(t) { 
     p->~T(); 
     operator delete(t, t1, ..., tn); // or T::operator delete(...); ?! 
    } 
} 

這可能是有問題的(你必須定義一個爲每個「delete運算符」,你必須要小心,因爲你不能處理全球版本和類成員版本相同的方式)。

總結:
我們有一個通用的新的表達式,但沒有一般的刪除表達式。 你知道背後的理由嗎?

+0

你能否詳細說明備註1?我看不到(void)* operator new(size_t,T1,T2,...,Tn);' –

+0

@ RomanZaytsev這個原型代表任何可能的「操作者新」。它可以例如表示用戶定義的重載版本。 – Flop

回答

1

注意,由於C++ 11和可變參數模板,可以作爲寫destroy一次:

// Helper to define has_operator_delete traits 
template <typename T, typename ...Ts> std::false_type has_operator_delete_impl(...); 
template <typename T, typename ...Ts> auto has_operator_delete_impl(int) 
-> decltype(std::declval<T>().operator delete(nullptr, std::declval<Ts>()...), 
      std::true_type{}); 

// traits to know if T has operator delete(void*, Ts...) 
template <typename T, typename ...Ts> 
using has_operator_delete = decltype(has_operator_delete_impl<T, Ts...>(0)); 

然後是destroy功能:

template<typename T, typename ...Ts> 
std::enable_if_t<has_operator_delete<T, Ts...>::value> 
destroy(T* t, Ts&&... ts) 
{ 
    if (t) { 
     t->~T(); 
     T::operator delete(t, std::forward<Ts>(ts)...); 
    } 
} 

template<typename T, typename ...Ts> 
std::enable_if_t<!has_operator_delete<T, Ts...>::value> 
destroy(T* t, Ts&&... ts) 
{ 
    if (t) { 
     t->~T(); 
     operator delete(t, std::forward<Ts>(ts)...); 
    } 
} 

Live Demo

我不t知道沒有一般刪除表達的基本原理。也許它在解析某處時引入歧義...

相關問題