Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

C++勉強会

3,341 views

Published on

  • Be the first to comment

C++勉強会

  1. 1. C++勉強会 C++勉強会 Mitsutaka Takeda Company 07 March 2012 . . . . . .
  2. 2. C++勉強会Outline 1 オブジェクトによるリソースの管理。 2 Interfaceの設計方法 3 標準ライブラリ STLの活用 4 防衛的プログラミング 5 参考情報 . . . . . .
  3. 3. C++勉強会 オブジェクトによるリソースの管理。Topic 1 オブジェクトによるリソースの管理。 2 Interfaceの設計方法 3 標準ライブラリ STLの活用 4 防衛的プログラミング 5 参考情報 . . . . . .
  4. 4. C++勉強会 オブジェクトによるリソースの管理。リソースとは? Bjarne Stroustrup (Software Development for Infrastructure) `A resource is anything that has to be acquired and released after use. . . . . . .
  5. 5. C++勉強会 オブジェクトによるリソースの管理。リソースの例 メモリ ファイル Mutex フォント ブラシ etc . . . . . .
  6. 6. C++勉強会 オブジェクトによるリソースの管理。リソース管理の問題点 使用後に解放しなければいけない。 解放しない(リークする)とリソースが不足する。例えばメモリ。 void f ( ) { MyClass * obj = new MyClass ( ) ; // リ ソ ー ス の 取 得 。 obj−>doSomething ( ) ; // リ ソ ー ス の 使 用 。 ... delete obj ; // リ ソ ー ス の 解 放 。 } 潜在不具合 リソースの使用中に例外を投げると、リソースが開放されない。 . . . . . .
  7. 7. C++勉強会 オブジェクトによるリソースの管理。リソースを確実に解放するため(その1) void f ( ) { MyClass * obj = NULL ; // リ ソ ー ス 用 変 数 を 宣 言 。 try{ obj = new MyClass ( ) ; // リ ソ ー ス の 取 得 。 obj− >doSomething ( ) ; // リ ソ ー ス の 使 用 。 ... } catch ( std : : ba d al l o c& e ){ i f ( obj != NULL ) // リ ソ ー ス の 使 用 中 に 例 外 を 投 げ る か も 。 delete obj ; // d e l e t e を 省 略 で き な い こ と に 注 意 。 } catch ( . . . ) { delete obj ; // そ の 他 の 例 外 。 } delete obj ; } 保守性に問題。(バグを混入しやすい) 処理が複雑。例外の種類により処理の切り替えが必要。 ソースコードの変更に対して脆い。 コードが冗長(delete文が沢山ある)。 . . . . . .
  8. 8. C++勉強会 オブジェクトによるリソースの管理。ソースコードの変更に対する脆弱性 例えば、保守担当者が不具合対策として以下のような変更を加えた場合。 void f ( ) { MyClass * obj = NULL ; // リ ソ ー ス 用 変 数 を 宣 言 。 try{ obj = new MyClass ( ) ; // リ ソ ー ス の 取 得 。 obj− >doSomething ( ) ; // リ ソ ー ス の 使 用 。 i f ( obj− >isSucceed ( ) ) r e t u r n ; // リ ソ ー ス ・ リ ー ク ! ! } catch ( std : : ba d al l o c& e ){ i f ( obj != NULL ) delete obj ; } catch ( . . . ) { delete obj ; } delete obj ; } . . . . . .
  9. 9. C++勉強会 オブジェクトによるリソースの管理。脆弱性に対する対策案(人に依存) コーディング規約(関数からのreturnは1箇所のみ等)による対策。 見逃したら? ソースコード・レビューで見逃さないようにする。 見逃したら? チェック・リストを作成して、レビュー時にチェックする。 見逃したら? ... 人はミスをするので、できるかぎりコンピュータに仕事をさせる。 マーフィーの法則 ``Anything that can go wrong will go wrong. . . . . . .
  10. 10. C++勉強会 オブジェクトによるリソースの管理。解決策(コンピュータに任せる) C++でのメモリ管理はオブジェクトに任せる。 RAII(Resource Acquisition Is Initialization)イディオム。 Javaやらガベージ・コレクション系の言語では無理!! . . . . . .
  11. 11. C++勉強会 オブジェクトによるリソースの管理。RAIIの基本的な考え方 ... 1 リソースの取得をオブジェクトの初期化(コンストラクタ)で行う。 ... 2 リソースの解放をオブジェクトの終了処理(デストラクタ)で行う。 C++の言語仕様で、コンストラクタが完了したオブジェクトの デストラクタの呼び出しが保証 されている。 MyClassのメモリ管理を行うクラス(スマート・ポインタの特殊ケース)。 c l a s s MyClassHandle{ public : MyClass * obj ; MyClassHandle ( ) { obj = new MyClass ( ) ; // コ ン ス ト ラ ク タ で リ ソ ー ス の 取 得 。 } ˜MyClassHandle ( ) { delete obj ; // デ ス ト ラ ク タ で リ ソ ー ス の 解 放 。 } }; . . . . . .
  12. 12. C++勉強会 オブジェクトによるリソースの管理。RAIIの適用(前) void f ( ) { MyClass * obj = NULL ; // リ ソ ー ス 用 変 数 を 宣 言 。 try{ obj = new MyClass ( ) ; // リ ソ ー ス の 取 得 。 obj− >doSomething ( ) ; // リ ソ ー ス の 使 用 。 ... } catch ( std : : ba d al l o c& e ){ i f ( obj != NULL ) delete obj ; } catch ( . . . ) { d e l t e obj ; } delete obj ; } 先程のコードにRAIIを適用すると。 . . . . . .
  13. 13. C++勉強会 オブジェクトによるリソースの管理。RAIIの適用(後) void f ( ) { // リ ソ ー ス 管 理 オ ブ ジ ェ ク ト を 生 成 ・ 初 期 化 ( = リ ソ ー ス の 取 得 ) MyClassHandle handle ; // リ ソ ー ス の 使 用 。 handle . obj−>doSomething ( ) ; ... }// f の 終 了 時 に デ ス ト ラ ク タ の 呼 び 出 し 。 注目点 適用後のコードではプログラマが自分でリソースの解放をしなくてもよいことに注目。 ハ ンドルがスコープをはずれると自動的にデストラクタが呼ばれてリソースが解放される。 たとえ例外が投げられても!! 適用前後のコード比較 コード量の減少 リソース・リークの防止 保守性の向上。コード変更後に処理の途中でreturnしてもリソース・リーク にならない。 . . . . . .
  14. 14. C++勉強会 オブジェクトによるリソースの管理。RAIIの応用 c l a s s Pen { public : HDC hdc ; HPEN new pen ; HGDIOBJ old pen ; Pen (HDC hdc , Color pen color ) : hdc ( hdc ) , old pen ( NULL){ new pen = CreatePen ( . . . ) ; // リ ソ ー ス の 取 得 。 i f ( new pen ) old pen = SelectObject ( hdc , new pen ) ; } ˜Pen ( ) { i f ( old pen ){ SelectObject ( hdc , old pen ) ; // 元 の ブ ラ シ に 戻 す 。 DeleteObject ( new pen ) ; // リ ソ ー ス の 解 放 。 } } }; . . . . . .
  15. 15. C++勉強会 オブジェクトによるリソースの管理。RAIIの応用 void draw ( ) { // 赤 色 の ペ ン を 作 成 。 r e d p e n オ ブ ジ ェ ク ト が 生 き て い る // ス コ ー プ で は 、 線 が 赤 色 に な る 。 r e d p e n オ ブ ジ ェ ク ト // が 破 壊 さ れ る と ペ ン の 色 は 、 元 の 色 に 戻 る 。 Pen red pen ( hdc , RED ) ; . . . // 描 画 。 } . . . . . .
  16. 16. C++勉強会 オブジェクトによるリソースの管理。RAIIを利用する際の注意点 ハンドル・クラスのコピー動作(コピー・コンスラクタと代入演算子)に注意!! MyClassHandle my obj1 ; MyClassHandle my obj2 ( my obj1 ) ; // コ ピ ー ・ コ ン ス ラ ク タ // リ ソ ー ス の 使 用 。 m y o b j 1 の o b j は ど う な る ? my obj2 . obj−>doSomething ( ) ; // void f ( i n t x ) ; 値 渡 し 。 i n t x = 3; f (x ); std : : cout < x < std : : endl ; // 3 と 表 示 。 < < // void g ( MyClassHandle obj ) 値 渡 し 。 MyClassHandle my obj3 ; g ( my obj3 ) ; // g の 呼 び 出 し 後 に m y o b j 3 の 状 態 は ? . . . . . .
  17. 17. C++勉強会 オブジェクトによるリソースの管理。RAIIのコピー動作 コピーを禁止 c l a s s MyClassHandle { private : // コ ピ ー ・ コ ン ス ラ ク タ と 代 入 演 算 子 を p r i v a t e 宣 言 。 // 実 装 は 必 要 な し 。 MyClassHandle ( const MyClassHandle & ) ; const MyClassHandle& operator =( const MyClassHandle & ) ; }; 参照カウントを利用してリソースを共有。(shared ptrの実装) . . . . . .
  18. 18. C++勉強会 オブジェクトによるリソースの管理。RAIIに関連してちょこっと脱線 リソースの取得はオブジェクトの初期化で行う。 オブジェクト初期化(生成)する時点で必要な 情報が全て揃っているのが理想。 できる限り初期化関数は避けましょう。 c l a s s BadClass{ public : void i n i t i a l i z e ( i n t x ) ; // 初 期 化 関 数 。 void doSomething ; }; BadClass obj ; // オ ブ ジ ェ ク ト の 生 成 ( 初 期 化 ) obj . i n i t i a l i z e ( 1 ) ; // 初 期 化 関 数 に よ る オ ブ ジ ェ ク ト の " 初 期 化 " obj . doSomething ( ) ; BadClass obj2 ; obj2 . doSoemthing ( ) ; // バ グ ! ! initializeの呼び出し前に他の関数 BadClass obj3 ; obj3 . i n i t i a l i z e ( 1 ) ; obj3 . i n i t i a l i z e ( 2 ) ; // 2回 初 期 化 関 数 を 呼 び 出 し て も 良 い ? . . . . . .
  19. 19. C++勉強会 オブジェクトによるリソースの管理。RAIIに関連してちょこっと脱線 初期化はコンストラクタで行う。 c l a s s BadClass{ public : BadClass ( i n t x ) ; void doSomething ( ) ; }; BadClass obj ( 1 ) ; obj . doSomething ( ) ; // 初 期 化 前 に 他 の 関 数 を 呼 び 出 せ な い 。 . . . . . .
  20. 20. C++勉強会 Interfaceの設計方法Topic 1 オブジェクトによるリソースの管理。 2 Interfaceの設計方法 3 標準ライブラリ STLの活用 4 防衛的プログラミング 5 参考情報 . . . . . .
  21. 21. C++勉強会 Interfaceの設計方法設計指針 Make interfaces easy to use correctly and hard to use incorrectly Effective C++ できるかぎり、コンパイラにエラーをチェックさせる。(マーフィーの法則) C++の型システムを利用する。 . . . . . .
  22. 22. C++勉強会 Interfaceの設計方法悪い例 その1 悪いインターフェイスの例。 パラメータの名前のみで、意味を区別しようとしている。 // 2点 間 の 距 離 を 計 算 。 i n t c a l c u l a t e D i s t a n c e ( i n t x0 , i n t y0 , i n t x1 , i n t y1 ) ; // ユ ー ザ 認 証 。 bool aut he n tic ate ( std : : s t r i n g password , std : : s t r i n g user name ) ; . . . . . .
  23. 23. C++勉強会 Interfaceの設計方法悪い例 その1 // 点 ( 1 , 3 ) と 点 ( 2 , 4 ) の 距 離 を 計 算 。 i n t distance = c a l c u l a t e D i s t a n c e ( 1 , 2 , 3 , 4 ) ; // バ グ ! ! i n t distance = c a l c u l a t e D i s t a n c e ( 1 , 3 , 2 , 4 ) ; // 正 し い 。 // ユ ー ザ を 認 証 。 std : : s t r i n g user name ( " user " ) ; std : : s t r i n g password ( " s e c r e t password " ) ; // バ グ ! ! ユ ー ザ 名 と パ ス ワ ー ド が 逆 。 bool i s a u t h e n t i c a t e d = auth ent icate ( user name , password ) ; // 正 し い 。 bool i s a u t h e n t i c a t e d = auth ent icate ( password , user name ) ; 使用方法を間違えても、誰も教えてくれない… . . . . . .
  24. 24. C++勉強会 Interfaceの設計方法改善 その1 小さなクラスを定義して利用する。 s t r u c t Point { Point ( i n t x , i n t y ) x (x) , y (y) { } int x ; int y ; } typedef unsinged i n t Distance ; // イ ン タ ー フ ェ イ ス ( 引 数 の 型 や 戻 り 値 の 型 ) を 見 た だ け で // 使 用 方 法 が 判 る 。 Distance c a l c u l a t e D i s t a n c e ( Point p1 , Point p2 ) ; . . . . . .
  25. 25. C++勉強会 Interfaceの設計方法改善 その2 typedef std : : s t r i n g Password ; typedef std : : s t r i n g User ; bool aut he n tic ate ( Password login password , User a user ) ; User my user name ( " user " ) ; Password my pass ( " s e c r e t password " ) ; bool i s a u t h e n t i c a t e d = auth ent icate ( my pass , my user name ) ; . . . . . .
  26. 26. C++勉強会 Interfaceの設計方法改善 その2 さらなる改善 typedefではコンパイル・エラーにはならないので注意。 User my user name ( " user " ) ; Password my pass ( " s e c r e t password " ) ; bool i s a u t h e n t i c a t e d = auth ent icate ( my user name , my password ) ; // バ グ ! ! コンパイラーにコードの正しさをチェックさせたいときは、クラスを利用する。 c l a s s User { ... }; c l a s s Password { ... }; 上記のコードはコンパイル・エラー。 . . . . . .
  27. 27. C++勉強会 Interfaceの設計方法脱線 typedefの効用 型名を短くできる。 typedef unsinged long long long MyType ; MyType my obj = . . . ; 型情報への参照を間接的にして局所化する。 typedef unsinged i n t Distance ; // ソ ー ス コ ー ド 中 の 色 々 な 場 所 で 、 Distance distance 1 = . . . ; ... Distance distance 100 = . . . ; Distanceに、unsinged intの最大値以上の値を保持する必要が。 typedefを使用していれ ば、変更箇所は1箇所ですむ。 型名にドキュメント情報(人が読むための情報として)。 . . . . . .
  28. 28. C++勉強会 Interfaceの設計方法悪い例 その2 リソースの取得と解放が別々の処理に分離されている。 MyClass * create ( ) ; void r e l e a s e ( MyClass * obj ) ; 問題点 クライアントがreleaseを呼び忘れたら? release以外の方法で、deleteされたら? . . . . . .
  29. 29. C++勉強会 Interfaceの設計方法改善 その3 生のポインタではなくスマートポインタを利用する。 boost : : shared ptr<MyClass> create ( ) ; もし、3rdパーティのライブラリで生のポインタを返すようにしている場合。 SomeonesClass * create ( ) ; void r e l e a s e ( SomeonesClass * obj ) ; shared ptrでは、解放の処理をカスタマイズできる。 // 第2 引 数 で 、 解 放 に 使 用 し た い 関 数 を 指 定 。 void f ( ) { boost : : shared ptr<SomeoneClass> p t r ( create ( ) , std : : p t r f u n ( r e l e a s e ) ) ; ptr−>doSomething ( ) ; }// 自 動 的 に 解 放 。 . . . . . .
  30. 30. C++勉強会 標準ライブラリ STLの活用Topic 1 オブジェクトによるリソースの管理。 2 Interfaceの設計方法 3 標準ライブラリ STLの活用 4 防衛的プログラミング 5 参考情報 . . . . . .
  31. 31. C++勉強会 標準ライブラリ STLの活用標準ライブラリを使用する利点 ...1 デバッグ済み(高い信頼性) ...2 他のプログラマに伝わりやすい(保守性) ...3 自動的に性能改善される可能性あり ...4 コードの記述量を減らすことができる バグの件数はソースコードのステップ数と相関 . . . . . .
  32. 32. C++勉強会 標準ライブラリ STLの活用STLの構造 container(データ構造) iterator algorithm IO 数値計算 internationalization 例外処理 . . . . . .
  33. 33. C++勉強会 標準ライブラリ STLの活用Container/Iterator/Algorithm Containerとは、複数のオブジェクトの集合を管理するためのコンポーネント。 Iteratorとは、Container中の要素にアクセスするためのコンポーネント。 Algorithmとは、Container中の要素を処理(検索、並びかえ)するためのコンポーネント。 . . . . . .
  34. 34. C++勉強会 標準ライブラリ STLの活用Container Sequence containers 順序付けられたcontainer。要素の順番はcontainerに追加した順番に依存。 vector deque list Associative containers 並びかえ済みcontainer。要素の追加時に指定した基準で要素を並びかえ。 set mutiset map multimap その他 Container Adapters(stack、queue、priority queue)、Cの配列。 . . . . . .
  35. 35. C++勉強会 標準ライブラリ STLの活用Iterator 反復子とよばれているContainer中の要素を指すオブジェクト。(Containerと Iteratorの関 係は、配列とポインタみたいなもの) Random access iterator Bidirectional iterator Forward iterator . . . . . .
  36. 36. C++勉強会 標準ライブラリ STLの活用Algorithm Container中の要素の範囲に特定の処理を行うためのライブラリ。 例: for each : Container中の全要素に対して処理を行う。 find : Container中から特定の要素を探す。 sort : Container中の要素を並びかえる。 . . . . . .
  37. 37. C++勉強会 標準ライブラリ STLの活用使用例 typedef std : : vector<i n t> numbers ; std : : vector<i n t> createNumbers ( ) { std : : vector<i n t> numbers ; f o r ( i n t i = 0; i < 10; ++ i ){ numbers . push back ( getRandomNumber ( ) ) ; } // 昇 順 に 並 べ 替 え 。 s o r t は デ フ ォ ル ト で (<) を 利 用 し て 並 べ 替 え る 。 std : : s o r t ( numbers . begin ( ) , numbers . end ( ) ) ; // 降 順 に 並 べ 替 え 。 g r e a t e r 関 数 を 利 用 し て 並 べ 替 え 。 std : : s o r t ( numbers . begin ( ) , numbers . end ( ) , greater<i n t > ( ) ) ; } . . . . . .
  38. 38. C++勉強会 標準ライブラリ STLの活用関数オブジェクト operator()をメンバ関数を保持するオブジェクト。STLを拡張するために利用する。 s t r u c t MyGreater{ bool operator ( ) ( i n t x , i n t y ) { return x > y ; } }; // 降 順 に 並 べ 替 え 。 M y G r e a t e r 関 数 オ ブ ジ ェ ク ト を 利 用 し て 並 べ 替 え 。 std : : s o r t ( numbers . begin ( ) , numbers . end ( ) , MyGreater ( ) ) ; . . . . . .
  39. 39. C++勉強会 標準ライブラリ STLの活用コーディング without STL(電話帳 氏名と電話番号を管理するプログラム) const i n t MAX SIZE(1000); Name *names = new Name[ MAX SIZE ] ; PhoneNumber phone numbers = new PhoneNumber [ MAX SIZE ] ; unsigned i n t s i z e = 0; void addRecord (Name name , PhoneNumber phone number ){ i f ( s i z e >= MAX SIZE ){ // 最 大 長 を 越 え て い る た め メ モ リ の 確 保 と デ ー タ の コ ピ ー 。 Name * new name data = new Name[2 * s i z e ] ; PhoneNumber * new phone number data = new PhoneNumber[2 * s i z e ] ; f o r ( i n t i = 0; i < s i z e ; ++ i ){ new name data [ i ] = names [ i ] ; new phone number data [ i ] = phone numbers [ i ] } Name *tmp1 = names ; PhoneNumber *tmp2 = phone numbers ; names = new name data ; phone numbers = new phone number data ; delete [ ] tmp1 ; delete [ ] tmp2 ; } // レ コ ー ド を 追 加 。 names [ s i z e ] = name ; phone numbers [ s i z e ] = phone number ; ++ s i z e ; } void sortPhoneBook (Name *names , PhoneNumber * phone numbers ){ . . . } . . . . . .
  40. 40. C++勉強会 標準ライブラリ STLの活用コーディング with STL typedef std : : pair<Name, PhoneNumber> RecordType ; typedef std : : vector<RecordType> PhoneBook ; PhoneBook my phone book ; void addRecord (Name name , PhoneNumber phone number ) { my phone book . push back ( std : : make pair ( name , phone number ) ) ; } void sortPhoneBook ( PhoneBook& phone book ){ // M y C r i t e r i a l は 自 分 が ソ ー ト し た い 基 準 を 表 現 す る 関 数 オ ブ ジ ェ ク ト 。 std : : s o r t ( phone book . begin ( ) , phone book . end ( ) , M y C r i t e r i a ( ) ) ; } . . . . . .
  41. 41. C++勉強会 標準ライブラリ STLの活用STLを利用するさいにも色々な注意点が。 それは次の機会に。 . . . . . .
  42. 42. C++勉強会 防衛的プログラミングTopic 1 オブジェクトによるリソースの管理。 2 Interfaceの設計方法 3 標準ライブラリ STLの活用 4 防衛的プログラミング 5 参考情報 . . . . . .
  43. 43. C++勉強会 防衛的プログラミング変数のスコープを最小限に // ル ー プ 変 数 ( i ) は 、 f o r の 初 期 化 ブ ロ ッ ク で 。 f o r ( i n t i = 0; i < N; ++ i ) { ... } void bad ( ) { // 関 数 の 頭 で 全 変 数 を 宣 言 。 i n t x = 0; std : : s t r i n g s t r ( "My name i s " ) ; ... s t r += " Takeda " ; ... ++x ; } void b e t t e r ( ) { ... std : : s t r i n g s t r ( "My name i s " ) ; s t r += " Takeda " ; ... i n t x = 0; ++x ; } void best ( ) { ... const std : : s t r i n g s t r ( "My name i s Takeda " ) ; ... i n t x = 1; . . . . . .
  44. 44. C++勉強会 防衛的プログラミングconstの活用 できる限りconstを使用する。 c l a s s MyClass { public : void doSomething ( ) const ; // c o n s t メ ン バ 関 数 。 }; void f ( const MyClass& obj ) ; // パ ラ メ ー タ の c o n s t 参 照 渡 し 。 void g ( ) { const double p i = 3.141592; // c o n s t ロ ー カ ル 変 数 。 } . . . . . .
  45. 45. C++勉強会 防衛的プログラミングイディオムを利用 イディオムとは? 経験のあるプログラマが利用するソース・コードの共通の書き方。 例えば、forループのイディオム。ループ条件にOpen-End(<)を利用することで、 要素数が0の 時を特殊ケース扱いとしなくてもよい(sizeが0のときは、ループは 実行されない)。 f o r ( i n t i = 0; i < s i z e ; ++ i ){ ... } イディオムの利点: イディオムを知っているプログラマ間で、ソースコードの理解性が向上する。 バグを発見しやすい。 . . . . . .
  46. 46. C++勉強会 参考情報Topic 1 オブジェクトによるリソースの管理。 2 Interfaceの設計方法 3 標準ライブラリ STLの活用 4 防衛的プログラミング 5 参考情報 . . . . . .
  47. 47. C++勉強会 参考情報書籍 The C++ Programming Language Effective C++ More Effective C++ Accelerated C++ The C++ Standard Library: A Tutorial and Reference Effective STL IEEE Computer Society January 2012 "Software Development for Infrastructure" . . . . . .
  48. 48. C++勉強会 参考情報リンク cplusplus.com http://www.cplusplus.com/ C++ FAQ http://www.parashift.com/c++-faq-lite/ More C++ Idioms(C++イディオム集) http://en.wikibooks.org/wiki/More C%2B%2B Idioms Going Native 2012 Keynote by Bjarne Stroustrup: C++11 style http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/ Keynote-Bjarne-Stroustrup-Cpp11-Style#+LTEX CLASS A . . . . . .

×