C++で=defaultと=deleteで使用

7682 ワード

コンパイラのデフォルトはクラス生成のデフォルト関数です.
  • デフォルトコンストラクタ
  • デフォルト構造関数
  • デフォルトコピーコンストラクタ
  • デフォルト付与関数
  • モバイルコンストラクタ
  • モバイルコピー関数
  • class DataOnly {
    public:
        DataOnly ()                  // default constructor
        ~DataOnly ()                 // destructor
    
        DataOnly (const DataOnly & rhs)              // copy constructor
        DataOnly & operator=(const DataOnly & rhs)    // copy assignment operator
    
        DataOnly (const DataOnly && rhs)         // C++11, move constructor
        DataOnly & operator=(DataOnly && rhs)    // C++11, move assignment operator
    };

    =delete
    1.コンパイラのデフォルトで生成された関数の使用を禁止
    上記のいくつかの関数のいずれかを使用したくない場合は、privateとして定義するか、=deleteとして使用します.
    #include 
    using namespace std;
    
    class DataOnly {
    public:
        DataOnly () {}
        ~DataOnly () {}
    
        DataOnly (const DataOnly & rhs) = delete; //       
        DataOnly & operator=(const DataOnly & rhs) = delete; //       
    
        DataOnly (const DataOnly && rhs) {}
        DataOnly & operator=(DataOnly && rhs) {}
    };
    
    int main(int argc, char *argv[]) {
        DataOnly data1;
        DataOnly data2(data1); // error: call to deleted constructor of 'DataOnly'
        DataOnly data3 = data1; // error: call to deleted constructor of 'DataOnly'
        return 0;
    }

    2.deleteキーワードは、クラスのメンバー関数に限らず、任意の関数に使用できます.
    #include 
    using namespace std;
    
    class DataOnly {
    public:
        void fun(int a) {}
        void fun(float a) = delete;
    };
    
    int main(int argc, char *argv[]) {
        DataOnly data1;
        data1.fun(1); // OK
        data1.fun(0.5); // error: call to member function 'fun' is ambiguous
        return 0;
    }

    3.テンプレート特化:テンプレート特例化ではdeleteで特定のパラメータタイプをフィルタできます.
    たとえば、Widgetクラスにテンプレート関数が宣言されています.テンプレートを特化する場合、パラメータがvoid*の関数呼び出しを禁止する必要があります. 1. の考え方によれば、特例化された関数を私有型として宣言すべきであり、以下のようにする.
    #include 
    using namespace std;
    
    class Widget {
    public:
        template
        void ProcessPointer(T* ptr) { 
            cout << typeid (T).name() << endl;
        }
    private:        
        void ProcessPointer(void*) { 
            cout << "void" << endl;
        }
    };
    
    int main(int argc, char *argv[]) {
        Widget w;
        int* ip = NULL;
        w.ProcessPointer(ip);
    
        void* vp = NULL;
        w.ProcessPointer(vp); //error: 'ProcessPointer' is a private member of 'Widget' w.ProcessPointer(vp);
        return 0;
    }
  • =deleteを直接後に追加すればこの問題を解決できる
  • = default
    プログラマが上記のC++コンパイラのデフォルトで生成された関数を再ロードした後、C++コンパイラはこれらの関数のデフォルト形式を生成しません.ただし、C++では、=defaultを使用してコンパイラにデフォルトの関数を生成するように要求できます.
    struct Point {
        Point()=default;
        Point(int _x, int _y) : x(_x), y(_y) {}
        int x = 0;
        int y = 0;
    }

    このように無参に相当する構造関数も使用可能である.
    この文書は次のとおりです.https://blog.csdn.net/lmb1612977696/article/details/80035487
    転載先:https://www.cnblogs.com/Malphite/p/11601414.html