明示的なdefault/delete関数
概要
C++11では、関数に対してdefault定義を自動で与えること、および関数を使用しないこと(delete定義)が記述可能になった。 以下で、それぞれについて説明する。
明示的なdefault関数
関数定義において、以下のような記述を、明示的なデフォルト化(explicitly-defaulted)定義と呼ぶ。そしてその関数をデフォルト化関数(defaulted function)と呼ぶ。
関数宣言 = default;
明示的なデフォルト化定義は、特別なメンバ関数に対してのみ適用でき、関数に暗黙の定義を与えることができる。このとき関数の型は暗黙的に宣言された場合と同じ形式である必要があり、デフォルト引数も持つことはできない。
特別なメンバ関数とは以下の6種類である。
種別 | シグネチャ | デフォルト定義時の動作 |
---|---|---|
デフォルトコンストラクタ | 型名() | メンバ初期化子が無く、本体が空 |
デストラクタ | ~型名() | 本体が空 |
コピーコンストラクタ | 型名(const 型名&) | メンバ毎のコピーをベースクラス、およびメンバ変数に対して実行 |
ムーブコンストラクタ | 型名(型名&&) | メンバ毎のムーブをベースクラス、およびメンバ変数に対して実行 |
コピー代入演算子 | 型名& operator=(const 型名&) | クラスのサブオブジェクトに対して、メンバ毎のコピー。この時、基本クラス(継承の記述順)、自身のメンバの順で実行 |
ムーブ代入演算子 | 型名& operator=(型名&&) | クラスのサブオブジェクトに対して、メンバ毎のムーブ。この時、基本クラス(継承の記述順)、自身のメンバの順で実行 |
デフォルト化関数には明示的なデフォルト化と暗黙的な宣言の両方が含まれ、定義内容はコンパイラ定義となり、定義内容には対象の関数が delete 関数として定義されることも含む。 delete定義される条件については規格を参照。
クラス宣言時に指定すると、その関数はインライン扱いとなる。 また、クラス宣言時とは異なる場所で、default指定による定義も可能である。その場合、その場所で定義されたものとして扱われる(インライン化されない)。 またこの時、対象の関数が暗黙的にdeleted関数として定義される場合は、ill-formedとなる。
class X{
public:
X() = default; //OK
X(int) = default; //error 特別なメンバ関数ではない
X(const X&) = default; //OK
X(X&&);
};
X::X(X&& v) = default; //OK インライン化されない
delete 関数
delete定義された関数をdelete関数(deleted function)と呼ぶ。delete定義とはコンパイラに対して、対象の関数が使用不可であることを明示することである。 delete定義は全ての関数に対して定義可能であり、delete定義された関数が、評価される/されないに関わらず参照される場合ill-formedとなる。
delete定義は最初の関数宣言時に指定しなければならない。
class X {
public:
X();
X(const X&) = delete; //OK
};
X::X() = delete; //error 最初の宣言ではない
struct sometype {
void *operator new(std::size_t) = delete;
void *operator new[](std::size_t) = delete;
}
sometype *p = new sometype; //error deleted関数の参照
sometype *q = new sometype[3]; //error deleted関数の参照