(2017年6月) 新規作成。
C++ では、互換性の観点と開発の便宜のため, 暗黙にコンストラクタ (構築子)、代入演算子、デストラクタ (破壊子) が定義される。自明 (trivial) な特殊メンバ関数と呼ばれる。
開発者が陽に (明示的に) これらのメンバ関数を定義した場合、自明なメソッドは定義されない。が、ややこしいことに, 単に対応するメンバ以外にも削除されるものがある。
表としてまとまったものが見当たらなかったので、作ってみた。
特殊メンバ関数とコンパイラによる暗黙宣言 - yohhoyの日記 や, コンストラクタが暗黙に宣言されるとき、されないとき があったが、残念なことに、2017年6月現在, 誤りが含まれている。
下の表は、一番左の列のメンバを陽に定義した場合に、2列目以降のメンバが自明か削除されるかを示す。trivial は自明なメンバが暗黙に定義され、deleted は削除される。
削除されても, = default
で自明なメンバを復活できる。
表中の noexcept
は例外を発生しない。false は潜在的に例外を発生しうる noexcept(false)
を表す.
Fedora 25 Linux の gcc 6.3.1 を用いた。デフォルトで C++14 (C++11と変わらない). また, c++1z でも変わらない。
下のメンバを定義したときに, 右のがどうなるか | default ctor | copy ctor | move ctor | copy assign | move assign | dtor |
---|---|---|---|---|---|---|
なし | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept |
default ctor | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | |
default ctor noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | |
copy ctor | deleted | trivial false | trivial noexcept | trivial noexcept | trivial noexcept | |
copy ctor noexcept | deleted | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | |
move ctor | deleted | deleted | deleted | deleted | trivial noexcept | |
move ctor noexcept | deleted | deleted | deleted | deleted | trivial noexcept | |
copy assign | trivial noexcept | trivial noexcept | trivial noexcept | trivial false | trivial noexcept | |
copy assign noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | |
move assign | trivial noexcept | deleted | deleted | deleted | trivial noexcept | |
move assign noexcept | trivial noexcept | deleted | deleted | deleted | trivial noexcept | |
dtor | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | trivial noexcept | |
dtor noexcept(false) | trivial false | trivial false | trivial false | trivial noexcept | trivial noexcept |
整理すると、次のようになる。
コメントアウトしたりして、試してみる。
コピー構築子を noexcept(false)
で定義すると、ムーブ構築子もそうなる、って一体何なんだ?
デフォルト構築子、コピー構築子、コピー代入演算子は、過去との互換性の確保から、noexcept
を強制できない。でも、ムーブ構築子、ムーブ代入演算子は、noexcept
を暗黙に指定してもよかったんじゃないかなぁ?