C++11 delete
簡介
delete
聲明的函數也會參與匹配,但是編譯階段就明確此類型的函數已被刪除.
delete
的錯誤可以在編譯階段發現.回顧
C++98
聲明爲
private
且不定義. 鏈接 階段才能發現.
delete
解決的問題
C++
編譯器
默認爲類創建: 無參構造,析構,拷貝,賦值四個函數.
衝突的就是: 拷貝賦值這兩個函數.
c++98
- 通過
private
私有聲明並不定義以此達到目的.但是隻能鏈接階段才能檢測到錯誤.代碼是先編譯,再鏈接,而鏈接是最後一步,最後一步才發現可能會過很久,特別是大型的項目編譯.
c++11
C++98
的手段在C++11
中被加強錯誤識別時間,編譯階段就可以識別出來.所以建議採用
C++11
而不是C++98
.隱式轉換
- 類型之間的隱式轉換也會導致不匹配的類型轉換調用。
- 可以通過聲明一個對應類型的聲明,然後標記爲
delete
就可以規避.不過之類比較麻煩.
隱式案例
void cool(int) {} void cool(bool) = delete; int main() { cool(1); cool(false); }
後面的會失敗.
兩種版本的編譯
[root@localhost test]# g++ -c test.cpp -std=c++98 [root@localhost test]# gcc test.o test.o: In function `main': test.cpp:(.text+0x1d): undefined reference to `cool(bool)' collect2: error: ld returned 1 exit status [root@localhost test]# cat test.cpp void cool(int) {} void cool(bool); int main() { cool(1); cool(false); } [root@localhost test]# vim test.cpp [root@localhost test]# g++ -c test.cpp -std=c++11 test.cpp: In function ‘int main()’: test.cpp:6:15: error: use of deleted function ‘void cool(bool)’ cool(false); ^ test.cpp:2:6: error: declared here void cool(bool) = delete; ^ [root@localhost test]# cat test.cpp void cool(int) {} void cool(bool) = delete; int main() { cool(1); cool(false); }
編譯階段發現錯誤.
差異
C++11
public
中聲明函數,並標記爲delete
.
private
則會先檢測權限再檢測是否delete
,得到錯誤信息.
C++98
私有不定義,在鏈接階段才能發現問題. 太遲了.
私有拷貝或者賦值對於友元或者成員中可能用到. 仍然只能在鏈接階段才發現.
delete
的強大
強大之處
什麼函數都可以
delete
. 普通函數,模板,類等等,幾乎所有.全局函數
delete
void cool(int) {} void cool(bool) = delete; int main() { cool(1); cool(false); }
這裏的案例不嚴謹,可能還有
const,volatile
之類的修飾會影響,但這裏僅僅是個案例.禁止模板實例化
template <typename T> void show(T a) {} template<> void show<bool>(bool) = delete; int main() { show(1); show(false); }
show(bool)
不能被實例化.這裏的案例也不是很完善,雖然也可能是
const,volatile
之類的.類成員
class T { public: template <typename T> void show(T a) {} template<> void show<bool>(bool) = delete; }; int main() { T a; a.show(1); a.show(false); }
編譯報錯,編譯器不允許在類中特例化.
只能在全局或者命名空間裏面.
C++11
標準版class T { public: template <typename T> void show(T a) {} }; template<> void T::show<bool>(bool) = delete; int main() { T a; a.show(1); a.show(false); }
還是報錯,不允許
bool
類型的特例化.
總結
C++98
的private
聲明不定義是可以,但是鏈接階段才能發現.
C++11
的public
中delete
則在編譯階段即可.
delete
支持禁止普通函數,模板函數,的實例化.更加強大.