皆さん、C++11でコーディングしてますか?
私は昨日Fedora9のノートPCに gcc 4.7.2 を手動インストールして、ようやくC++11を書くことのできる環境を手に入れました。
C++11にはたくさんの新仕様がありますが、その中でも私が好きな仕様の一つが default
指定です。
C++のクラスでコンストラクタやデストラクタ等の記述を省略するとコンパイラがそれらを自動生成しますが、その「コンパイラに自動生成させる」ことを明示できる仕様です。
1
2
3
4
5
6
7
8
9
10
| - | | | | | | | ! |
|
上述のコードにおいて = default
の記述がある宣言は書いても書かなくても生成されるクラスは同じです。
しかし書かなかった場合、他の人がコードを読んだ時に「コンパイラに自動生成させようとしている」のか、「単に書き忘れた」のかが区別できません。
敢えて default
指定の宣言を記述することで、「私はこれらをコンパイラに自動生成させています」というアピールになります。
また、他の人だけでなく、コンパイラにもその意図を明示的に伝えることができ、コンパイラによっては最適化の助けになる可能性もあるでしょう。
C++11では、特別な処理をさせる場合を除き、記述を省略したりましてや空っぽの実装を書いたりせずに default
指定を積極的に用いるべきです。
特にデストラクタについては、リソースの解放はメンバ変数に任せてヘッダファイルでの default
指定を義務化するくらいのつもりで考えるべきでしょう。
そしてそれらのメンバ変数を辿った先は、基本型、データ抽象クラス(std::string
等)、各種スマートポインタクラスのいずれかに行き着くようにします。
その辺りの話は次のWebページが参考になります。
ただ、すべてのデストラクタをヘッダファイルで default
指定できるかというと例外があります。
これらのうち、3番目の「デストラクタをインライン展開できない場合」に当てはまるものの1つにpimplイディオムがあります。
詳しくは上のWebページに書かれていますが、pimplイディオムを知っているという前提で簡単に説明します。
上述のコードのようにクラス宣言の中でデストラクタを default
指定で宣言した場合、自動生成されるデストラクタはコンパイラによってインライン展開されます。
するとその場で _impl
メンバのデストラクタも呼び出す必要があるため、 std::unique_ptr<Impl>
クラスの実体化が試みられますが、 Var::Impl
クラスは前方宣言しかされていないために実体化することができず、コンパイルエラーとなるわけです。
これは default
指定の代わりに空のデストラクタを書いても同じことで、解決するためにはデストラクタの実装を Var::Impl
クラスの完全な定義が見える場所に記述する必要があります。
しかし、 default
指定は何も宣言部でなければ書けないものではありません。
むしろ default
指定は「宣言として書くもの」ではなく、「実装(関数本体)の代わりとして書くもの」と考えた方がいいです。
例えば上述のコードではデストラクタ Var::~Var()
の動作は既定のものでよいため、空の実装を書く代わりに default
指定を用いて次のように書くこともできます。
13 |
|
今回はこの「pimplイディオムを用いたクラスのデストラクタでも default
指定できるよ!」ということだけ言いたかったのですが、何故かやたら長くなってしまいました…。
ともあれ、 default
指定は非常に有用ですので、C++11でコードを書く際には是非活用しましょう。