Sapporocpp#2 exception-primer

1,963 views

Published on

sapporo.cpp #2

Published in: Technology, Business
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,963
On SlideShare
0
From Embeds
0
Number of Embeds
19
Actions
Shares
0
Downloads
26
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Sapporocpp#2 exception-primer

  1. 1. 例外安全入門 @hotwatermorning
  2. 2. 自己紹介● @hotwatermorning● はてなid:heisesswasser● 大学生● DTMやってます● C++が好きです● 「プログラミングの魔導少女」では 「RangeとPStade.Oven」という記事を書かせ ていただきました。
  3. 3. C++erなら
  4. 4. 誰しもメモリーリークに
  5. 5. 悩まされたことがあるはず
  6. 6. 今回のセッションは
  7. 7. その悩みを
  8. 8. 軽減する
  9. 9. 軽減する かもしれない
  10. 10. 本日のレシピ1.例外安全とは?2.例外安全性の種類3.例外安全なコードを書くには4.例外安全にするための技法
  11. 11. 本日のレシピ1.例外安全とは?2.例外安全性の種類3.例外安全なコードを書くには4.例外安全にするための技法いわゆる、エラーハンドリング/例外ハンドリング関連の内容●は含んでおりません。
  12. 12. 本日のレシピ1.例外安全とは?2.例外安全性の種類3.例外安全なコードを書くには4.例外安全にするための技法● いわゆる、エラーハンドリング/例外ハンドリング関連の内容は含んでおりません。● というかそれは僕も知りたいので誰か教えt(ry
  13. 13. 1.例外安全とは?
  14. 14. 例外安全とは?「あるコード内を実行中の失敗が、メモリリーク、格納データの不整合、不正な出力などの有害な効果を生じないとき、そのコード片は例外安全であると言う。」“例外処理”http://ja.wikipedia.org/wiki/%E4%BE%8B%E5%A4%96%E5%87%A6%E7%90%86
  15. 15. 例外安全とは?「例外安全なプログラミングとは、 例外を投げる可能性があるコードが実際に例外を投げた場合に、 プログラムの状態が壊れずリソースもリークしないように作るプログラミングのことを言います。 」“例外安全なプログラミング”http://www.kmonos.net/alang/d/2.0/exception-safe.html
  16. 16. 例外安全とは?● 例外が発生しても適切に対処できるよう なコードを書く。● 適切に対処しないと・・・ ‣ メモリリーク、リソースリーク ‣ 中途半端な操作の完了 ‣ デストラクタから例外が投げられる と・・・
  17. 17. 例外安全でないコードの例(1)void SampleClass::ReadData(int n){ delete [] data_; data_ = new T[n]; read_data(data_, n);}
  18. 18. 例外安全でないコードの例(1)void SampleClass::ReadData(int n){ delete [] data_; data_ = new T[n]; //←ここや read_data(data_, n);}
  19. 19. 例外安全でないコードの例(1)void SampleClass::ReadData(int n){ delete [] data_; data_ = new T[n]; //←ここや read_data(data_, n);//←ここで}
  20. 20. 例外安全でないコードの例(1)void SampleClass::ReadData(int n){ delete [] data_; data_ = new T[n]; //←ここや read_data(data_, n);//←ここで} //例外が投げられると...??
  21. 21. 例外安全でないコードの例(1)void SampleClass::ReadData(int n){ delete [] data_; data_ = new T[n]; //←ここや read_data(data_, n);//←ここで} //例外が投げられると...??SampleClassの状態が壊れてしまう!!
  22. 22. 例外安全でないコードの例(2)SampleClass2 & SampleClass2::operator= (SampleClass2 const &rhs){ data1_ = rhs.data1_; data2_ = rhs.data2_; data3_ = rhs.data3_; data4_ = rhs.data4_; return *this;}
  23. 23. 例外安全でないコードの例(2)SampleClass2 & SampleClass2::operator= (SampleClass2 const &rhs){ data1_ = rhs.data1_; data2_ = rhs.data2_;//このうち data3_ = rhs.data3_; data4_ = rhs.data4_; return *this;}
  24. 24. 例外安全でないコードの例(2)SampleClass2 & SampleClass2::operator= (SampleClass2 const &rhs){ data1_ = rhs.data1_; data2_ = rhs.data2_;//このうち data3_ = rhs.data3_;//どれかで data4_ = rhs.data4_; return *this;}
  25. 25. 例外安全でないコードの例(2)SampleClass2 & SampleClass2::operator= (SampleClass2 const &rhs){ data1_ = rhs.data1_; data2_ = rhs.data2_;//このうち data3_ = rhs.data3_;//どれかで data4_ = rhs.data4_;//例外が起きたら return *this;}
  26. 26. 例外安全でないコードの例(2)SampleClass2 & SampleClass2::operator= (SampleClass2 const &rhs){ data1_ = rhs.data1_;//これはどうなる? data2_ = rhs.data2_;//このうち data3_ = rhs.data3_;//どれかで data4_ = rhs.data4_;//例外が起きたら return *this;}
  27. 27. 例外安全なコードじゃないと
  28. 28. 例外が起きたときにきちんと対処できない
  29. 29. よし、
  30. 30. 例外安全なコードを書こう!
  31. 31. と、そのまえに
  32. 32. 2.例外安全性の種類
  33. 33. 例外安全性の種類● 例外を投げない保証 高● 強い例外安全 例外安全性● 基本的な例外安全● 例外安全保証なし 低
  34. 34. 例外安全性の種類● 例外を投げない保証● 強い例外安全 但し・・・● 基本的な例外安全● 例外安全保証なし
  35. 35. 例外安全性の種類● 例外を投げない保証 高● 強い例外安全 コスト…● 基本的な例外安全● 例外安全保証なし 低
  36. 36. 例外安全性の種類● 例外安全保証なし
  37. 37. 例外安全性の種類 ● 例外安全保証なし● その関数や呼び出し先で例外が起きると リソースがリークしてしまうかもしれな い・・・
  38. 38. 例外安全性の種類 ● 例外安全保証なしvoid SampleClass::ReadData(int n){ delete [] data_; data_ = new T[n]; read_data(data_, n);}
  39. 39. 例外安全性の種類● 基本的な例外安全の保証
  40. 40. 例外安全性の種類 ● 基本的な例外安全の保証● 例外が投げられても、いかなるリソース もリークしない。
  41. 41. 例外安全性の種類 ● 基本的な例外安全の保証● 例外が投げられても、いかなるリソース もリークしない。● 副作用は出るかもしれない(データの変 更や出力など。)
  42. 42. 例外安全性の種類 ● 基本的な例外安全の保証● 例外が投げられても、いかなるリソース もリークしない。● コンテナの中で例外が発生した場合、一 貫性は保っているが、予測可能な状態と は限らない。● なのでその後、削除や再利用はできる。
  43. 43. 例外安全性の種類 ● 基本的な例外安全の保証void SampleClass::ReadData(int n){ delete [] data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); } catch(...) { delete [] data_; data_ = 0; }}
  44. 44. 例外安全性の種類● 強い例外安全の保証
  45. 45. 例外安全性の種類 ● 強い例外安全の保証● 例外が起きたなら、全ての変更は ロールバックされる● 完全な成功か、例外による完全な失 敗かの2つの状況になる
  46. 46. 例外安全性の種類 ● 強い例外安全の保証void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; }}
  47. 47. 例外安全性の種類● 例外を投げない保証(no throw)
  48. 48. 例外安全性の種類 ● 例外を投げない保証(no throw)● 操作は全て正しく完了されることが 保証される。
  49. 49. 例外安全性の種類 ● 例外を投げない保証(no throw)● 操作は全て正しく完了されることが 保証される。● 例)基本データ型の代入などは例外 が起きない
  50. 50. 例外安全性の種類 ● 例外を投げない保証(no throw)● 操作は全て正しく完了されることが 保証される。● 例)基本データ型の代入などは例外 が起きない● 呼び出し先も例外を投げない保証が できなければならない
  51. 51. 例外安全性の種類● 例外を投げない保証(no throw)void foo(){ int n1 = 0x10; int n2 = n1; int *pn1 = &n1; int *pn2 = pn1;}
  52. 52. 3.例外安全なコードを書くには
  53. 53. 例外安全なコードを書くには● ある実行パス中の例外安全性は、その工 程で一番低いものになる。
  54. 54. 例外安全なコードを書くには● ある実行パス中の例外安全性は、その工 程で一番低いものになる。● どゆこと?
  55. 55. 例外安全なコードを書くにはint baz() { return bar() * bar(); }void foo(){ int n1 = 1; //例外安全なコード int n2 = bar(); //例外安全でないコード int n3 = 3; //例外安全なコード int n4 = baz(); //例外安全でないコード}
  56. 56. 例外安全なコードを書くには(さっきの「強い例外安全」のサンプルコード)void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; }}
  57. 57. 例外安全なコードを書くには(さっきの「強い例外安全」のサンプルコード)void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); //←もしこの関数が delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; }}
  58. 58. 例外安全なコードを書くには(さっきの「強い例外安全」のサンプルコード)void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); //←もしこの関数が delete [] tmp; //例外安全じゃないと } catch(...) { delete [] data_; data_ = tmp; }}
  59. 59. 例外安全なコードを書くには(さっきの「強い例外安全」のサンプルコード)void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); //←もしこの関数が delete [] tmp; //例外安全じゃないと } catch(...) { //ReadData関数は delete [] data_; d...//完全な例外安全とは } //言えなくなる}
  60. 60. 例外安全なコードを書くには● ある実行パス中の例外安全性は、その工 程で一番低いものになる。● 呼び出し先の例外安全性にも左右されて しまう。
  61. 61. 例外安全なコードを書くには● ある実行パス中の例外安全性は、その工 程で一番低いものになる。● 呼び出し先の例外安全性にも左右されて しまう。● プログラムの中で基本的な機能であるほ ど、しっかりした例外安全性を実装して いなければならない。(コンテナなど)
  62. 62. 例外安全なコードを書くには● ある実行パス中の例外安全性は、その工 程で一番低いものになる。● 呼び出し先の例外安全性にも左右されて しまう。● プログラムの中で基本的な機能であるほ ど、しっかりした例外安全性を実装して いなければならない。(コンテナなど)● 標準のコンテナは大体強い保証を満たす
  63. 63. 例外安全なコードを書くには● それぞれの関数で例外を投げうる部分と 投げない部分を明確に分離する。● 本来の処理の成功を確認した時点で、例 外を投げない部分を使って、状態の変更 と後処理を行うようにする。
  64. 64. 例外安全なコードを書くには● 例外中立について
  65. 65. 例外安全なコードを書くにはvoid SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; }}
  66. 66. 例外安全なコードを書くにはvoid SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; } //例外安全に書けましたね!}
  67. 67. 例外安全なコードを書くにはvoid SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; } //でもいざ例外が起きたときに}
  68. 68. 例外安全なコードを書くにはvoid SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; } //ReadDataの呼び出し元は} //ここで起きた例外をなにも知らない
  69. 69. 例外安全なコードを書くには● 例外中立について● コンテナなどで例外が起きると、その例 外が起きるまでのコンテキストを知って いるのは呼び出し元だけ。
  70. 70. 例外安全なコードを書くには● 例外中立について● コンテナなどで例外が起きると、その例 外が起きるまでのコンテキストを知って いるのは呼び出し元だけ。● コンテナでは、自分の行った範囲の例外 は安全に処理できるけど、他は無理。
  71. 71. 例外安全なコードを書くには● 例外中立について● コンテナなどで例外が起きると、その例 外が起きるまでのコンテキストを知って いるのは呼び出し元だけ。● コンテナでは、自分の行った範囲の例外 は安全に処理できるけど、他は無理。● 適切に処理できるところまでは例外を正 しく伝える。
  72. 72. 例外安全なコードを書くにはvoid SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; }}
  73. 73. 例外安全なコードを書くにはvoid SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; //正しくはこう。 }}
  74. 74. 例外安全なコードを書くには● 単一の関数にatomicでない複数の処理が あると、例外安全の強い保証をするのは 不可能。● 例)std::coutに出力してからstd::cerr に出力
  75. 75. 4.例外安全にするための技法
  76. 76. これまでのことは
  77. 77. いまから紹介する2つのテクニックの
  78. 78. 布石に過ぎなかった
  79. 79. 布石に過ぎなかった \ばばーん/
  80. 80. 例外安全にするための技法● いままで説明してきたことを上手く実装 するためのテクニック
  81. 81. 例外安全にするための技法● いままで説明してきたことを上手く実装 するためのテクニック● Swap
  82. 82. 例外安全にするための技法● いままで説明してきたことを上手く実装 するためのテクニック● Swap● RAII(Resource Acquisition Is Initialization)
  83. 83. 例外安全にするための技法 ● Swap● 実体を他に作って、全て成功した ら、変更したいリソースとSwapする
  84. 84. 例外安全にするための技法 ● Swap● 実体を他に作って、全て成功した ら、変更したいリソースとSwapする● Swapは、例外を投げない保証を必ず 守る
  85. 85. 例外安全にするための技法template<typename T>void swap(T &lhs, T &rhs){ T tmp = lhs; lhs = rhs; rhs = tmp;}
  86. 86. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //頑張って強い例外安全にしてるけど}
  87. 87. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //ロールバック用にいろいろ書いてて}
  88. 88. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //例外を投げる部分が}
  89. 89. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //例外を投げない部分に囲まれて}
  90. 90. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //Try-Catchも入り乱れて}
  91. 91. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //ちょっと複雑・・・}
  92. 92. 例外安全なコードを書くには● それぞれの関数で例外を投げうる部分と 投げない部分を明確に分離する。● 本来の処理の成功を確認した時点で、例 外を投げない部分を使って、状態の変更 と後処理を行うようにする。
  93. 93. 例外安全にするための技法 ● Swap● 実体を他に作って、全て成功した ら、変更したいリソースとSwap
  94. 94. 例外安全にするための技法 ● Swap● 実体を他に作って、全て成功した ら、変更したいリソースとSwap例外を投げうる部分 投げない部分
  95. 95. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = new T[n]; //先に確保 try { read_data(tmp, n);//そいつで処理 } catch(...) { delete [] tmp; } std::swap(data_, tmp);//終わったら入れ替え delete [] tmp; //後処理}
  96. 96. 例外安全にするための技法 ● Swap● 例外を投げうる部分と投げない部分を明 確に分離● 例外を投げる部分が成功したら例外を投 げない部分で状態を変更● ロールバック用のTry-Catchは要らなく なる!
  97. 97. 例外安全にするための技法 ● Swap● 例外を投げうる部分と投げない部分を明 確に分離● 例外を投げる部分が成功したら例外を投 げない部分で状態を変更● ロールバック用のTry-Catchは要らなく なる! (リソース管理用のは必要・・・)
  98. 98. 例外安全にするための技法 ● Swap● 自作クラスでも、 Copy-Constructableなクラスなら swapを実装する。
  99. 99. 例外安全にするための技法void SampleClass::swap(SampleClass &rhs){ //標準のswap関数や std::swap(data_, rhs.data_); //それ用のswap関数などで other_data_.swap(rhs.other_data_);}
  100. 100. 例外安全にするための技法 ● Swap● 自作クラスでも、 Copy-Constructableなクラスなら swapを実装する。● SampleClass (SampleClass const &rhs);
  101. 101. 例外安全にするための技法 ● Swap● 自作クラスでも、 Copy-Constructableなクラスなら swapを実装する。● 実装すると・・・
  102. 102. 例外安全にするための技法 ● Swap● 自作クラスでも、 Copy-Constructableなクラスなら swapを実装する。● Assignableなクラスに出来る。● SampleClass & operator=(SampleClass const &)
  103. 103. 例外安全にするための技法SampleClass & SampleClass::operator= (SampleClass const &rhs){ //コピーコンストラクタ SampleClass tmp(rhs); //swap tmp.swap(*this); return *this;}
  104. 104. 例外安全にするための技法SampleClass & SampleClass::operator= (SampleClass const &rhs){ //コピーコンストラクタ SampleClass tmp(rhs); //swap tmp.swap(*this); さらにまとめて return *this; 書くと}
  105. 105. 例外安全にするための技法SampleClass & SampleClass::operator= (SampleClass const &rhs){ SampleClass(rhs).swap(*this); return *this;}
  106. 106. 例外安全にするための技法SampleClass & SampleClass::operator= (SampleClass const &rhs){ SampleClass(rhs).swap(*this); return *this;} メンバ変数がAssignableであることを 要求しない
  107. 107. 例外安全にするための技法SampleClass & SampleClass::operator= (SampleClass const &rhs){ SampleClass(rhs).swap(*this); return *this;} Copy And Swap
  108. 108. 例外安全にするための技法 ● RAII● 「リソースの確保は初期化である」
  109. 109. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //リソース管理のためにコードが複雑に}
  110. 110. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //deleteも分散してしまった}
  111. 111. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; } //対応していない}
  112. 112. 例外安全にするための技法 ● RAII● 「リソースの確保は初期化である」● コンストラクタでリソースを確保● デストラクタでリソースを破棄
  113. 113. 例外安全にするための技法 ● RAII● 「リソースの確保は初期化である」● コンストラクタでリソースを確保● デストラクタでリソースを破棄 対応!!
  114. 114. 例外安全にするための技法 ● RAIIclass RAIIClass{ RAIIClass(Resource r) : r_(r) {} RAIIClass(Args as) : r_(CreateResource(as)) {} ~RAIIClass() { DisposeResource(r_); }private: Resource r_;};
  115. 115. 例外安全にするための技法 ● RAII● これをメモリ管理に使ったのがいわ ゆるスマートポインタ
  116. 116. 例外安全にするための技法 ● RAII● これをメモリ管理に使ったのがいわ ゆるスマートポインタ● プログラマはリソース解放のめんど くささから解放される!
  117. 117. 例外安全にするための技法 ● RAII● これをメモリ管理に使ったのがいわ ゆるスマートポインタ● プログラマはリソース解放のめんど くささから解放される!● 例外安全とか考えなくても使うべ き!
  118. 118. 例外安全にするための技法 ● RAII● これがどのように例外安全性の点で 重宝されるのか?
  119. 119. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; }}
  120. 120. 例外安全にするための技法 ● RAII● Deleteのために例外をCatchしなく ちゃいけなかった
  121. 121. 例外安全にするための技法 ● RAII● Deleteのために例外をCatchしなく ちゃいけなかった● でもRAIIなクラスを使うと、Delete は自動化できる
  122. 122. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; これが read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; throw; }}
  123. 123. 例外安全にするための技法void SampleClass::ReadData(int n){ shared_array<T> tmp = data_; try { data_.reset(new T[n]); こうなる read_data(data_, n); } catch (...) { data_ = tmp; }}
  124. 124. 例外安全にするための技法 ● RAII● どこで起きるかわからないような例 外によって関数を抜けるときも、そ の時に自動でリソースが解放され る!● リソース解放のためのTry-Catchは要 らなくなる!
  125. 125. 例外安全にするための技法 ● RAII● どこで起きるかわからないような例 外によって関数を抜けるときも、そ の時に自動でリソースが解放され る!● リソース解放のためのTry-Catchは要 らなくなる!(強い例外安全保証の ためのは必要・・・)
  126. 126. 例外安全にするための技法 ● SwapとRAII
  127. 127. 例外安全にするための技法 ● SwapとRAII1.Swapはロールバック用のTry- Catchを不要にする。
  128. 128. 例外安全にするための技法 ● SwapとRAII1.Swapはロールバック用のTry- Catchを不要にする。2.RAIIはリソース管理用のTry- Catchを不要にする。
  129. 129. 例外安全にするための技法 ● SwapとRAII1.Swapはロールバック用のTry- Catchを不要にする。2.RAIIはリソース管理用のTry- Catchを不要にする。3.例外中立のために、例外が起き てもいじらないで伝える。
  130. 130. 例外安全にするための技法 ● SwapとRAII 合体
  131. 131. 例外安全にするための技法void SampleClass::ReadData(int n){ shared_array<T> tmp(new T[n]); read_data(tmp_, n); std::swap(data_, tmp);}
  132. 132. 例外安全にするための技法void SampleClass::ReadData(int n){ shared_array<T> tmp(new T[n]); read_data(tmp_, n); std::swap(data_, tmp);} おわかりいただけただろうか
  133. 133. 例外安全にするための技法void SampleClass::ReadData(int n){ shared_array<T> tmp(new T[n]); read_data(tmp_, n); std::swap(data_, tmp);} おわかりいただけただろうか ではもう一度・・・
  134. 134. 例外安全にするための技法void SampleClass::ReadData(int n){ T *tmp = data_; data_ = 0; try { data_ = new T[n]; read_data(data_, n); delete [] tmp; } catch(...) { delete [] data_; data_ = tmp; }}
  135. 135. 例外安全にするための技法void SampleClass::ReadData(int n){ shared_array<T> tmp(new T[n]); read_data(tmp_, n); std::swap(data_, tmp);}
  136. 136. 例外安全にするための技法 ● SwapとRAII● 適切なコードを書けば、例外安全 性のためにTry-Catchを書く必要 はない。
  137. 137. 例外安全にするための技法 ● デストラクタで例外
  138. 138. 例外安全にするための技法 ● デストラクタで例外● 禁止!
  139. 139. 例外安全にするための技法 ● デストラクタで例外● 禁止!● 配列を安全にできない● 例外が起きたときにスタックの巻 き戻しを安全にできない● 全ての例外安全の努力が水の泡!
  140. 140. 5.まとめ
  141. 141. まとめ● 例外安全なコードを書くには
  142. 142. まとめ● 例外安全なコードを書くには● 例外を投げる部分と投げない部分を 分離して、例外のある処理の成功を 確認してから、状態を変更する。● RAIIを使用してリソースの管理を自 動化する
  143. 143. まとめ● 今回の内容はほとんど全て 「Exceptional C++」 (ハーブ・サッター著) に書かれています● あと「C++ Coding Standard」も
  144. 144. おしまい。

×