Your SlideShare is downloading. ×
C++11 (他) 入門
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

C++11 (他) 入門

14,513
views

Published on

Published in: Technology

0 Comments
34 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
14,513
On Slideshare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
127
Comments
0
Likes
34
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. C++11 (他) 入門 ~ Java, C, +αを学んだ貴方へ(というのは真っ赤な嘘) Yuta Hirokawa, @krustf/総長1 2012/2/15
  • 2. 内容, 注意 Effective C++ の重要そうな部分を独断で抜き出し C++11 の規格で直結しそうな機能を幾つか紹介 テンプレートに関するテクニックを少々解説 最新規格 C++11(旧称C++0x) に則る  ウェブページや書籍では未だC++0x表記による情報が多い 検索時は気を付けること 2 導入 2012/2/15
  • 3. 注意 C++11 完全対応コンパイラは未だ無い  2012年2月14日現在 当スライドでは以下の環境を使用する 一部以下の環境では使えないコードがある(かも) Compiler gcc 4.5 Build Option -std=gnu++0x Service ideone.com 3 導入 2012/2/15
  • 4. C++11 機能の対応表 http://wiki.apache.org/stdcxx/C++0xCompilerSupport  last edited 2012-02-13 GCC や Clang がC++11の対応状況が良い MSVC はお粗末なので止めて下さい(切実)  海外のページでMSVC10か11の悲惨な対応状況によって MSの開発者ブログが炎上しました 4 導入 2012/2/15
  • 5. 選りすぐり Effective C++ 10の項目 ここはさらさらやります5 2012/2/15
  • 6. 1. #define よりも const, enum, inline ! define は文字列の置換であり型情報が無い 文字列置換によるマジック(関数や変数の自動生成等) でない限りインライン関数の方が良い strongly typed enum(C++11)により強い型安全なenumを 使用する事が可能 6 Effective C++ から 2012/2/15
  • 7. 1. #define よりも const, enum, inline !// #define PI 3.14...const double PI = 3.14159265358979;// #define pow2(x) x * xinlinetemplate<class T>T pow2(T const& v) { return v * v; }7 Effective C++ から 2012/2/15
  • 8. strongly typed enum 直訳 「強い型付けの列挙子」 これまでと違いenum名をスコープとして列挙子名を指定 列挙子の型を指定できるように(従来はint型)enum class Color : std::uint32_t { Red, Green, Blue, White, Black, Yellow};Color c = Color::Green;// Color c = White; error!! 8 Effective C++ から 2012/2/15
  • 9. 2. 可能な限り const を使う 「変更不可」を明示しコンパイラにその制約を守るための 手助けを要請するもの 本来書き変えない部分における書き変えを防ぎ コンパイル時にバグを未然防止する クラスにおいて読み取り専用のメンバ関数には必ず const を付ける(const メンバ関数) 9 Effective C++ から 2012/2/15
  • 10. const メンバ関数 そのメンバ関数内でのクラスのインスタンス変数を一切 変更できなくする 「論理的な不変性」(関わるデータ全ての変更禁止) 「ビットレベルでの不変性」(データメンバの変更禁止)struct hoge { double x; double get_x() const { // x *= 2; error!! return x; }}; 10 Effective C++ から 2012/2/15
  • 11. 3. constructorとdestructorを使う ctor と dtor は C++ のクラスが自動生成を行う  自動生成されたものは default ctor/dtor と呼ばれる 自動生成ではなく独自に引数を指定して作成可能  但し、その場合default ctor/dtor は自動生成されない 自動生成して欲しくない関数は delete する  default and deleted function 11 Effective C++ から 2012/2/15
  • 12. 3. constructor と destructor を使うclass complex {public: complex() : r(), i() {}; complex(double _r, double _i) : r(_r), i(_i) {};private: double r, i;};12 Effective C++ から 2012/2/15
  • 13. default and deleted function 自動生成してほしいものを default 生成禁止してほしいものを deleteclass hoge { hoge() = default; hoge(hoge const&) = delete; // copy の禁止 hoge& operator=(hoge const&) = delete;};hoge h;// h = hoge(); Error!! 13 Effective C++ から 2012/2/15
  • 14. 4. 仮想デストラクタを無暗に付けない 動的ポリモルフィズムの場合, デストラクタに virtual を 付けて仮想デストラクタにする必要がある しかし, 無暗に全てのクラスのデストラクタにつけることは パフォーマンス低下や作者の意図していない継承となり バグの発生につながる 14 Effective C++ から 2012/2/15
  • 15. 5. デストラクタから例外を絶対に投げない アクティブ(発生している)な例外が複数あると undefined-behavior(未定義動作)となる デストラクタから例外を投げる設計では, アクティブな 例外が複数個発生しやすい デストラクタで例外を補足した場合はデストラクタ内で 適切な処理をする必要がある  abort で強制終了  デストラクタで握りつぶす(飲み込む) 15 Effective C++ から 2012/2/15
  • 16. 6. ctor と dtor では仮想関数を呼ばない 基底クラスが, 派生クラスによってオーバーライドされた 仮想関数を呼び出す場合, ctor 内では派生クラスの データメンバの初期化を終了していない 初期化されていない値を使用してしまう! 初期化順番:基底クラスから派生クラス 破棄の順番:派生クラスから基底クラス 16 Effective C++ から 2012/2/15
  • 17. 7. リソース管理は RAII を使う RAII (Resource Acquisition Is Initialization)  「リソースの確保が初期化」 リソースの確保と管理クラスの初期化は同タイミング コンストラクタでリソースを確保、管理クラスの初期化 デストラクタで自動的に削除 17 Effective C++ から 2012/2/15
  • 18. 7. リソース管理は RAII を使うstruct File { std::FILE* fp; explicit File(std::FILE* _fp) : fp(_fp) {}; ~File() { if(fp) std::fclose(fp); };};void save_file(std::string const& path) { File file(std::fopen(path.c_str(), "w")); std::fwrite(...); ...} // auto file close.18 Effective C++ から 2012/2/15
  • 19. std::shared_ptr, std::unique_ptr C++11 で追加された RAII によるリソース管理クラス 基本的には new で確保された動的領域の管理 shared_ptr は色々な関数で使う共有オブジェクト用 unique_ptr はクラス内部のみなど固有オブジェクト用 shared_ptr atomic access などもある(説明省略) 19 Effective C++ から 2012/2/15
  • 20. 8. 値渡しより const 参照渡しを使う 値渡し(コピー)では大きなサイズの配列のコピー操作に 時間がかかってしまい無駄が大きい const 参照によってコピーを防ぎ, さらに意図しない改竄 を防ぐことができる  copy ctor が禁止されているクラスでも使える const 参照では, const メンバ関数のみが使用可能 20 Effective C++ から 2012/2/15
  • 21. 8. 値渡しより const 参照渡しを使うtemplate<class T>void func(std::vector<T> const& v) { // v.push_back(42); error!! std::cout << v[0] << std::endl; // v[0] = 2; error!!}21 Effective C++ から 2012/2/15
  • 22. 9.C++スタイルキャストを使う static_cast  明示的な型変換を行う reinterpret_cast  低レベルキャスト(ポインタ間変換等)を行う dynamic_cast  安全なダウンキャストを行う(基底クラスから派生クラスへ)  実行コストが高い const_cast  const を取り外す際に使われる, 付加も可能  但し, 外した後のデータを変更した場合の動作は未定義 22 Effective C++ から 2012/2/15
  • 23. 9.C++スタイルキャストを使うstd::uint32_t i = 42;std::int32_t j = static_cast<std::int32_t>(i);void* ptr = get_ptr();char* cptr = reinterpret_cast<char*>(ptr);const char* s = "hello, world";char* ss = const_cast<char*>(s);23 Effective C++ から 2012/2/15
  • 24. 10. 継承よりコンポジションを先に考える 継承はクラスの公開メンバを増やしてしまう  クラスの使用者にとって不要なものも増える クラスのコンポジション(合成)によって, 必要な機能のみ を組み合わせて公開メンバとすることで外部への情報を すっきりさせる 24 Effective C++ から 2012/2/15
  • 25. C++11 の必要そうな機能 途中に説明したものに加えて25 2012/2/15
  • 26. 1. Angle bracket 従来テンプレート内にテンプレートが入る場合 連続した山かっこが operator>> などに勘違いされた コンパイラに勘違いされないようになった// C++03std::vector<std::vector<int> > v;// C++11std::vector<std::vector<int>> v 26 C++11 2012/2/15
  • 27. 2. Initializer list ユーザ定義クラスで配列のような 初期化構文を提供可能に STL クラスも対応std::vector<int> v = { 1, 2, 3 };v[0] == 1;v[1] == 2;v[2] == 3; 27 C++11 2012/2/15
  • 28. 3. auto 戻り値による型推論  これにより, C++03 時代での auto との互換性が削除 関数テンプレート内でのローカル変数などに使う コンパイラが知る情報に任せて面倒な型名を省略std::vector<int> v;auto b = v.begin(); // is vector<int>::iteratorauto e = v.end(); // is vector<int>::iterator 28 C++11 2012/2/15
  • 29. 4. decltype sizeof の型推論版 ある計算によって戻ってきた型を調べるint i = 42;double pi = 3.141592;decltype(i); // intdecltype(i + pi); // double 29 C++11 2012/2/15
  • 30. 5. Range-based for 他言語にはよくある foreach 構文std::vector<int> v = { 1, 2, 3, 4, 5 };for(auto& i : v) { i *= 2;}for(auto i : v) { std::cout << i << std::endl;} 30 C++11 2012/2/15
  • 31. 6. Lambda expressions ラムダ式 匿名の関数オブジェクトを生成 関数オブジェクトや関数を作る手間がある程度省ける 外のスコープの変数を参照も可能 31 C++11 2012/2/15
  • 32. 6. Lambda expressionsauto f = [](int i) -> int { return i * i; };int result = f(2); // result == 4;std::vector<int> v = { 1, 2, 3, 4, 5 };int sum = 0;std::for_each( v.begin(), v.end() , [&](int i) { sum += i; });// sum == 1532 C++11 2012/2/15
  • 33. 追加機能は非常に多い コア言語サポートだけではない 導入された新たなクラスや関数の一部  shared_ptr インスタンスの共有  unique_ptr インスタンスの所有  unordered ハッシュマップ  thread 標準スレッドライブラリ  random メルセンヌツイスタ等の乱数生成 33 C++11 2012/2/15
  • 34. テンプレートの美味しい調理法 しっかりサンプルコードがあります34 2012/2/15
  • 35. 静的ポリモルフィズム 動的ポリモルフィズムは「実行時」に動作内容を決める 「コンパイル時」に動作内容を決めるのが 静的ポリモルフィズムと言える テンプレートを用い, 様々な方向で静的ポリモルフィズム を実現できる 35 テンプレートテクニック 2012/2/15
  • 36. 1. Tag Dispatch 型に応じて適切な関数を呼び分ける 外部公開する関数は1つだが, 内部では型に応じて 複数の関数を呼び分けるのが一般的 その型は Tag として空のクラスで定義する 36 テンプレートテクニック 2012/2/15
  • 37. 1. Tag Dispatchstruct hoge_tag {};struct foo_tag {};struct hoge { typedef hoge_tag call_tag; };struct foo { typedef foo_tag call_tag; };namespace detail { void call_(hoge_tag) { std::cout << "hoge." << std::endl; }; void call_(foo_tag) { std::cout << "foo." << std::endl; };}; 37 テンプレートテクニック 2012/2/15
  • 38. 1. Tag Dispatchtemplate<class T>void call(T) { typedef typename T::call_tag call_tag; detail::call_(call_tag());}call(hoge()); // "hoge."call(foo()); // "foo." 38 テンプレートテクニック 2012/2/15
  • 39. 1. Tag Dispatch 前述の方法では, call_tag がないとビルドエラーになる tag が無い場合に汎用的な処理をしたい時がある Traits を使って tag の取り出しを問い合わせるcall(int()); // not typedef call_tag // エラーにせず汎用処理がしたい 39 テンプレートテクニック 2012/2/15
  • 40. 2. Traits ある型 T に対する情報をコンパイル時に問い合わせる STL では iterator_traits などが有名 テンプレートの特殊化によって ある型に対する情報を個別に設定する 40 テンプレートテクニック 2012/2/15
  • 41. 2. Traitstemplate<class T> struct call_traits { typedef T call_tag;};template<> struct call_traits<hoge> { typedef hoge::call_tag call_tag;};template<> struct call_traits<foo> { typedef foo::call_tag call_tag;}; 41 テンプレートテクニック 2012/2/15
  • 42. 2. Traitsnamespace detail { void call_(hoge_tag) { ... }; void call_(foo_tag) { ... }; template<class T> void call_(T) { std::cout << "other." << std::endl; };}; 42 テンプレートテクニック 2012/2/15
  • 43. 2. Traitstemplate<class T>void call(T) { typedef typename call_traits<T>::call_tag call_tag; detail::call_(call_tag());}call(hoge()); // "hoge."call(foo()); // "foo."call(int()); // "other." - http://ideone.com/3vmIv 43 テンプレートテクニック 2012/2/15
  • 44. 余談:MPI の MPI_Datatype を型から取得template<class T> struct mpi_data_type {};template<> struct mpi_data_type<float> { static MPI_Datatype apply() { return MPI_FLOAT; }};template<> struct mpi_data_type<double> { static MPI_Datatype apply() { return MPI_DOUBLE; }};mpi_data_type<float>::apply(); // MPI_FLOATmpi_data_type<double>::apply(); // MPI_DOUBLE 44 テンプレートテクニック 2012/2/15
  • 45. 2.7182. 階乗を静的に求めるtemplate<int N>struct factorial { static const int value = factorial<N-1>::value * N;};template<>struct factorial<0> { static const int value = 1;};std::size_t result = factorial<5>::value; // 120 - http://ideone.com/R8ZFz 45 テンプレートテクニック 2012/2/15
  • 46. 3. TMP - Template Meta Programming イメージとしてプログラムを生成するためのコード 様々なメタ関数を駆使することで実現  テンプレートのインスタンス化を利用して 様々な計算をコンパイル時に行う 先ほどの factorial もメタ関数 46 テンプレートテクニック 2012/2/15
  • 47. 3. TMP - Template Meta Programming メタ関数は  再帰でループを表現  特殊化で条件分岐 factorial メタ関数は  再帰でループ計算  特殊化で 0 の際は 1 を返すようにする ヘルパを駆使するのが一般的  Boost.MPL が素晴らしい 47 テンプレートテクニック 2012/2/15
  • 48. 4. Type Erasure C++ の超静的型処理は迷惑 テンプレートでは動的な型処理が困難 型情報を消し, 動的型処理の手助けを行う 非テンプレート基本クラスとテンプレート派生クラス 2つを用いて型情報を消すのが一般的 例として, あるメンバ関数を型に寄らず呼び出してみる 48 テンプレートテクニック 2012/2/15
  • 49. 4. Type Erasurestruct any { template<class T> any(T const& i) : _erasure() { _erasure = new derive<T>(i); } any() = default; template<class T> any& operator=(T const& i) { if(_erasure) { delete _erasure; }; _erasure = new derive<T>(i); } void call() const { _erasure->call(); }; 49 テンプレートテクニック 2012/2/15
  • 50. 4. Type Erasureprivate: struct base { virtual ~base() {}; virtual void call() = 0; }; template<class U> struct derive : public base { U val; derive(U const& i) : val(i) {}; void call() { val.call(); }; }; base* _erasure;}; 50 テンプレートテクニック 2012/2/15
  • 51. 4. Type Erasurestruct hoge { void call() const { std::cout << "hoge::call" << std::endl; };};struct foo { void call() const { std::cout << "foo::call" << std::endl; };};any val;val = hoge();val.call(); // "hoge::call"val = foo();val.call(); // "foo::call" - http://ideone.com/3Z8Lr 51 テンプレートテクニック 2012/2/15
  • 52. 5. SFINAE Substitution Failure Is Not An Error  置き換え失敗はエラーではない テンプレートの置き換えに失敗した場合 その関数等を呼び出し候補から外す 関数テンプレートのオーバーロード解決を補佐する 機能として重宝されることが多い コードが分かりづらくなりやすい 52 テンプレートテクニック 2012/2/15
  • 53. 5. SFINAE Boost.MPL やメタ関数を使い倒す 疲れたので, ideone にのみ掲載 サンプルでは, 配列かそうでないかで出力を切替 http://ideone.com/1JpTD 53 テンプレートテクニック 2012/2/15
  • 54. 参考文献 Effective C++ 第3版, スコットメイヤーズ, 2006/05, ピアソンエデュケーション C++ テンプレートテクニック, επιστημη 高橋晶, 2009/04, ソフトバンククリエイティブ C++11 Working Draft N3337, 2012/01/16  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/ 54 2012/2/15
  • 55. 参考文献 本の虫 - http://cpplover.blogspot.com/ Faith and Brave - C++ で遊ぼう - http://d.hatena.ne.jp/faith_and_brave/ cpprefjp - https://sites.google.com/site/cpprefjp/ C++11 Advent Calender 2011 - http://atnd.org/events/21936 55 2012/2/15

×