C++ 11 delete

  • 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++98private聲明不定義是可以,但是鏈接階段才能發現.

    • C++11publicdelete則在編譯階段即可.

    • delete支持禁止普通函數,模板函數,的實例化.更加強大.

  • 發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章