サイボウズ・ラボの光成です。
今年の1月から『Effective Modern C++』(Scott Meyers)の読書会を社外の人を含めて月1回のペースで始め、先月末に無事最後まで終わりました。 その感想をざっと紹介いたします。
『Effective Modern C++』(以下EMCと略)はC++11/C++14で追加された様々な新しい機能について紹介する本です。 従って、C++の全くの初心者が読むには少々難しいと思います。以前のC++にある程度習熟した人が、新機能の注意点を勉強したいというときに使うとよいでしょう。 本には重要な間違いもいくつか指摘されていますので正誤表の確認はしておきましょう。
なおこの9月には日本語版(千住治郎訳)も登場しています。こちらは7月時点で原書に見つかっている正誤表が反映されていてうれしいですね。
C++11ではautoの型推論、typedefより高機能なusing、高機能なenum、一般化された定数を扱うconstexpr、スマートポインタ、move、ラムダ式、threadなど多数の機能が追加されています。 ここでは詳細にはふれません。 WikipediaのC++11やStandard C++からたどれる規格書のドラフトなどを参照してください。
EMCも網羅的に解説しているのではなくそれらのうちの一部を重点的に解説しています。 EMC勉強会でみなさんが発表された資料はGitHubのemcjp勉強会に置いています。
ここでは個人的に面白かったトピックを中心にざっくりと紹介しましょう。
型推論(1~2章)
読み始めると、いきなりテンプレートの型推論という高度な話から始まって少々驚いたのですが、autoキーワードを正しく使うには必須の事項なので、いままでなんとなく理解していたという人は読んでおくとよいでしょう。
www.slideshare.net
型推論1章は上記日本語版の関連ファイルから無料で読めます。 なお、著者がこの本で使用している独自用語universal referenceはC++の規格としてはforwarding referenceという名前で使われ始めています(cf. N4164)。
初心者がautoを使ったときに陥りやすい点を一つだけ挙げると、
std::vector<std::string> vs;
の全要素を参照だけしたい(改変はしない)ときに
for (auto s : vs) { 中身を参照するだけ }
というコードを書いて予想外のパフォーマンス低下に悩まないようにしてください。
ここでは
const auto& sにする必要があります。 そうしないとループの中で毎回文字列のコピーが発生するからです。
nullptr, using, enum, override, noexcept(3章)
これらは新しく追加されたり、より便利になった機能の中ではそれほど落とし穴はありません。それぞれの該当個所を参照していただけたら使えると思います。
スマートポインタ(4章)
まずはいままでのauto_ptrの使用を止めてunique_ptrに移行することだけ覚えるとよいでしょう。
www.slideshare.net
shared_ptrは便利だといってむやみに使わず、できるだけそれを使わないでもメモリ管理ができるか考える方がよいと思います。
右辺値参照、move, perfect forwarding(5章)
これらの概念はなかなか難しいです。 標準ライブラリを使うだけなら自然にその恩恵を受けることが多いと思いますが、自分で作るライブラリを対応させるときはこの章をきちんと理解する必要があります。 Item 17で紹介される暗黙に生成されるメンバ関数についても合わせて見ておきましょう。
www.slideshare.net
またコピーとmoveとどう使い分けるべきかについてはItem 41で紹介される関数の引数の扱いに関する考察もじっくり読むとよいでしょう。
ラムダ式(6章)
複雑なことはせず、STLの比較関数をその場で入れるなどちょっとしたことのみに使うという方針をとれば、落とし穴にはまることなくその恩恵を十分受けられると思います。
www.slideshare.net
並行API(7章)
個人的には意外だったのですが、この本ではstd::threadよりもstd::asyncを使った手法を推していました。 threadを使うよりは気軽なのですが、それでいろいろ落とし穴があるのでデフォルトの仕様をきちんと理解する必要があります。
www.slideshare.net
std::threadに関しては「joinせずに破棄するな」ということを忘れてはいけません。
もう一ひねり(8章)
std::stringを例にインスタンスの生成、コピー、moveについて非常に精密な議論を展開します。 たとえばstd::stringを引数にとるという単純なメソッドの設計についても、文字列リテラルを渡したとき、既に値が設定されているとき、一度長い文字列が設定されたときなど様々な状況でのコストを比較します。 C++の面倒なところでもあり、自由度の高さを示す章でもあると思います。
www.slideshare.net
おわりに
上記リンクした資料は一部です。emcjp勉強会には他のItemの資料もアップされています。参考にしてください。
また面白そうな本やトピックが見つかればこうした勉強会を開きたいと思います。
最後になりましたが平日夜の開催ながらも参加して発表したり、活発な議論をしてくださったみなさまに感謝します。