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++ ポインタ ブートキャンプ

17,391 views

Published on

Sapporo.cpp & CLR/H 合同勉強会 ( http://atnd.org/events/33614 ) で発表したスライドです。

Published in: Technology
  • Hi there! I just wanted to share a list of sites that helped me a lot during my studies: .................................................................................................................................... www.EssayWrite.best - Write an essay .................................................................................................................................... www.LitReview.xyz - Summary of books .................................................................................................................................... www.Coursework.best - Online coursework .................................................................................................................................... www.Dissertations.me - proquest dissertations .................................................................................................................................... www.ReMovie.club - Movies reviews .................................................................................................................................... www.WebSlides.vip - Best powerpoint presentations .................................................................................................................................... www.WritePaper.info - Write a research paper .................................................................................................................................... www.EddyHelp.com - Homework help online .................................................................................................................................... www.MyResumeHelp.net - Professional resume writing service .................................................................................................................................. www.HelpWriting.net - Help with writing any papers ......................................................................................................................................... Save so as not to lose
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❶❶❶ http://bit.ly/2u6xbL5 ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Sex in your area is here: ❶❶❶ http://bit.ly/2u6xbL5 ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD THI5 BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download doc Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD THI5 BOOKS 1NTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... Download doc Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

C++ ポインタ ブートキャンプ

  1. 1. C++ポインタ ブートキャンプ @hotwatermorning Sapporo.cpp&CLR/H 合同勉強会
  2. 2. 自己紹介• @hotwatermorning• Sapporo.cpp• DTMer• 7/7のプロ生勉強会で発表など
  3. 3. サラリーマン100人 に聞きました。• 「C++のポインタのイメージ」
  4. 4. サラリーマン100人 に聞きました。• 「C++のポインタのイメージ」 よく分からない 難しい 触りたくない トラウマ 俺が規格書だ
  5. 5. ちょうどC, C++の ポインタを学んでいる人や
  6. 6. ポインタ周りの構文で嵌っている人向け
  7. 7. 本日の訓練メニュー• 第一部 「ポインタの基礎」• 第二部「ポインタの嵌りどころ」• 第三部「ポインタを使わない」
  8. 8. 第一部ポインタの基礎
  9. 9. ポインタの基礎• ポインタとは、 何らかのオブジェクトを指す オブジェクト
  10. 10. ポインタの基礎• ポインタとは、 何らかのオブジェクトを指す オブジェクト
  11. 11. ポインタの基礎• オブジェクトとは、 変数の定義やnew-式などによって メモリ上に確保され占有された 領域のこと “オブジェクトはdefinition(3.1), new-式(5.3.4), あるいはimplementation(12.2)によって作成される” (1.8/1) “a most derived objectは0ではないサイズを持ち、1byte以上の領域をメモリ上で占有する。” (1.8/5) Working Draft, Standard for Programming Language C++ (N3337) より。
  12. 12. int main(){ int i;}この時、変数iはint型のオブジェクト。たとえば変数iはメモリ上で0x7fff5fbfea54から始まる数バイトの領域を占有している。(アドレスは実行毎に変わりうる)
  13. 13. int main(){ int i;}この占有しているサイズは型ごとに固有で、sizeof(type)で取得できる。intが4バイトの処理系では、sizeof(int)は4を返し、変数iは0x7fff5fbfea54から始まる4バイトの領域を占有する。
  14. 14. ・・・ 0x7fff5fbfea4f int main() 0x7fff5fbfea50 { 0x7fff5fbfea51 int i; 0x7fff5fbfea52 } 0x7fff5fbfea53 0x7fff5fbfea54この占有しているサイズは型ごとに 0x7fff5fbfea55 i 0x7fff5fbfea56固有で、sizeof(type)で取得できる。 0x7fff5fbfea57intが4バイトの処理系では、 0x7fff5fbfea58 0x7fff5fbfea59sizeof(int)は4を返し、 0x7fff5fbfea5a 0x7fff5fbfea5b変数iは0x7fff5fbfea54から始まる4バイトの領域 0x7fff5fbfea5c 0x7fff5fbfea5dを占有する。 0x7fff5fbfea5e ・・・
  15. 15. int main(){ int i; i = 3;}このプログラムはメモリ上の0x7fff5fbfea54にint型の3を書き込んでいる
  16. 16. int main(){ int i; i = 3;}変数iの占有する領域(0x7fff5fbfea54)を知っているのは変数iだけ。つまり、0x7fff5fbfea54から始まる4バイトに対する値の読み書きは、今のところ変数i経由でしか行えない。
  17. 17. int main(){ int i; i = 3;}この時、変数iからオブジェクトのアドレス(0x7fff5fbfea54)が取得でき、アドレスの先にあるオブジェクトに対して、何バイトかの値を直接読み書きできるような仕組みがあれば・・・
  18. 18. 擬似コード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる AnyPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるオブジェクトを操作する! ! assert(i == 3): }
  19. 19. 擬似コード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる AnyPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で元になる変数を使わずに、 ! //その位置にあるオブジェクトを操作する!アドレス経由でメモリを読み書きして、 ! assert(i == 3): }オブジェクトを操作できる。
  20. 20. ポインタの基礎• ポインタは オブジェクトのアドレスを保持す るオブジェクト• ポインタ変数なんて呼ばれたりも する
  21. 21. ポインタの基礎• ポインタは オブジェクトのアドレスを保持す るオブジェクト• アドレスを経由して、アドレスが 指すオブジェクトを操作できる
  22. 22. ポインタの基礎• だだし、前ページの擬似コードに は欠陥がある。
  23. 23. 擬似コード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる AnyPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるオブジェクトを操作する! ! assert(i == 3): }
  24. 24. 擬似コード int main() { char i;//例えば変数iのオブジェクトは //0x7fff5fbfea54にいる AnyPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるオブジェクトを操作する! ! assert(i == 3): }
  25. 25. 擬似コード int main() { std::list<int> i;//例えば変数i... //0x7fff5fbfea54にいる AnyPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるオブジェクトを操作する! ! assert(i == 3): }
  26. 26. 擬似コード int main() { MyClass i;//例えば変数i... //0x7fff5fbfea54にいる AnyPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるオブジェクトを操作する! ! assert(i == 3): }
  27. 27. ポインタの基礎• 前ページの擬似コードで使用して いるAnyPointerはアドレス値を保存 するだけ。• アドレスの先にあるオブジェクト の型は知らない。
  28. 28. ポインタの基礎• なんのオブジェクトに対する アドレスなのか• 型ごとにその型のアドレスを扱う ためのポインタ
  29. 29. 擬似コード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる AnyPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるオブジェクトを操作する! ! assert(i == 3): }
  30. 30. 擬似コード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる IntPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるint型のオブジェクトを //操作する! ! assert(i == 3): }
  31. 31. ポインタの基礎• int型にはIntPointerのような型• charにはCharPointerのような型• MyClassにはMyClassPointer(ry• これがあれば、アドレスからその 先のオブジェクトを操作できる
  32. 32. 擬似コード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる IntPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるint型のオブジェクトを //操作する! ! assert(i == 3): }
  33. 33. 実際のコード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる int * pi = &i;! ! //piの値は0x7fff5fbfea54 *pi = 3; ! //piに代入されているアドレス経由で ! //その位置にあるint型のオブジェクトを //操作する! ! assert(i == 3): }
  34. 34. ポインタの基礎• 擬似コードと実際に動く コードでの文法の対応• IntPointer → int *• addressof(i) → &i• indirect(i) → *i
  35. 35. ポインタの基礎• 擬似コードでのポインタの型と 実際に動くコードでの型の対応• IntPointer → int *• CharPointer → char *• MyClassPointer → MyClass *
  36. 36. ポインタの基礎• ポインタの文法
  37. 37. ポインタの宣言• T型のオブジェクトへのポインタの 変数を宣言する際には、 変数を*(indirection演算子)で修飾す る T!*!pt; // T*!pt; T!*pt; T*pt; とも書ける。
  38. 38. アドレスの取得• T型の変数tやオブジェクトの左辺 値があるとき &t; で、オブジェクトのアドレスを 取得できる
  39. 39. アドレスの取得• T型の変数tやオブジェクトの左辺 値があるとき &t;• 上記のコードで、tに前置している 単項演算子&はaddress-of演算子と いう
  40. 40. アドレスの取得• T型の変数tやオブジェクトの左辺 値があるとき &t;• このように、変数に&演算子を 前置した式は、tのアドレスを保持 するポインタを返す
  41. 41. ポインタへの代入• T型の変数tとT型のオブジェクト へのポインタptがあるとき、 pt = &t; このようにして、address-of演算子 が返すポインタを別のポインタに 代入できる
  42. 42. ポインタの間接参照• T型のオブジェクトへのポインタpt があるとき、 *pt; このようにして、アドレスの先に あるオブジェクト(のlvalue)を取得 できる
  43. 43. ポインタの間接参照• そのため、取得したオブジェクト に対して、 *pt = *pt + 1; このようにして、値を読み書きで きる• (上記のコードは、ptが指す先のオブジェクトに1を加えている。)
  44. 44. ポインタの間接参照 *pt;• このように、ポインタからその アドレスの位置にある オブジェクトを参照する操作を 間接参照(indirection) という。
  45. 45. ポインタの間接参照 *pt;• 上記のコードで、ポインタに前置 している単項演算子*は indirection演算子や dereference演算子という
  46. 46. ポインタの間接参照 *pt;• このように、ポインタに*演算子を 前置した式は、ptの指すアドレス の位置にあるオブジェクト (のlvalue)を返す。
  47. 47. 再掲int main(){ int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる。 int * pi = &i;!! //piの値は0x7fff5fbfea54 *pi = 3;! //piに代入されているアドレス経由で! //その位置にあるint型のオブジェクトを //操作する!! assert(i == 3):}
  48. 48. メンバアクセスの構文• ポインタでクラスを扱うときは、 非ポインタの時とメンバアクセス の構文が異なる。
  49. 49. struct Time { int hour; int minutes; int seconds;};int main(){ Time t; t.hour = 6; t.minutes = 19; t.seconds = 00;}
  50. 50. struct Time { int hour; int minutes; int seconds;};int main(){ Time t; Time *pt = &t; pt->hour = 6; pt->minutes = 19; pt->seconds = 00;}
  51. 51. メンバアクセスの構文• オブジェクトから直接メンバに アクセスするときは、 operator.(ドット演算子)を使用するt.access_to_member_;t.invokeMemberFunction();
  52. 52. メンバアクセスの構文• ポインタから間接参照して オブジェクトのメンバにアクセス するときは、operator->(アロー演 算子)を使用するpt->access_to_member_;pt->invokeMemberFunction();
  53. 53. newとポインタ• C++で、動的にオブジェクトを生 成するには、new演算子を使用す る。
  54. 54. int main(){ int *pi = new int(); *pi = 1; delete pi;}
  55. 55. int main(){ MyClass *pm = new MyClass(); *pm = 1; delete pm;}
  56. 56. int main() { MyClass *pm = new MyClass(); *pm = 1; delete pm; }new-式によるオブジェクトの生成は、まずメモリ上にその型の領域が確保され、次にオブジェクトのコンストラクタが実行され、最後に作成されたオブジェクトへのポインタが返る。
  57. 57. int main() { MyClass *pm = new MyClass(); *pm = 1; delete pm; }先程までの例では変数iなどが、0x7fff5fbfea54のようなアドレスにあるオブジェクトを直接表していたために、変数iによって、0x7fff5fbfea54の領域を直接読み書きできた。
  58. 58. int main() { MyClass *pm = new MyClass(); *pm = 1; delete pm; }しかし、new-式によって生成されたオブジェクトは、メモリ上にオブジェクトの領域は確保されても、直接そのオブジェクトを指す変数はない。
  59. 59. int main() { MyClass *pm = new MyClass(); *pm = 1; delete pm; }そのため、new-式から返るポインタ経由で間接的に、オブジェクトを扱うことになる。
  60. 60. int main() { MyClass *pm = new MyClass(); *pm = 1; delete pm; }また、new-式によって確保されたメモリ領域は明示的に解放しない限り、プログラムが終了するまでメモリ上に残り続ける。使用する必要がなくなった段階でdelete演算子にポインタを渡して解放する必要がある。
  61. 61. 第二部ポインタの嵌りどころ
  62. 62. ポインタの嵌りどころ• 構文がややこしい• 多重ポインタ• constの付加
  63. 63. ポインタの嵌りどころ• 構文がややこしい• 多重ポインタ• constの付加
  64. 64. int main(){! int i = 3;! int *pi = &i; *pi = *pi + 1;}
  65. 65. int main(){! int i = 3;! int *pi = &i; *pi = *pi + 1;}色々なところに*piが現れてる!!
  66. 66. int main(){! int i = 3; int *pi = &i; *pi = *pi + 1;}
  67. 67. 宣言時の構文と変数• 宣言時に、これから宣言するオブ ジェクトがポインタだと指定する ために*演算子を使用する。 int *pi;• 変数自体はあくまで pi;
  68. 68. int main(){! int i = 3; int *pi = &i; *pi = *pi + 1;}
  69. 69. int main(){! int i = 3; int *pi; //ポインタの宣言と pi = &i; //代入を分けて書くと *pi = *pi + 1;}
  70. 70. int main(){! int i = 3; int *pi; //ポインタの宣言と pi = &i; //代入を分けて書ける *pi = *pi + 1;}
  71. 71. int main() { ! int i = 3; int *pi; //ポインタの宣言と pi = &i; //代入を分けて書ける *pi = *pi + 1; } 間接参照(元のオブエジェクト: 変数iを取得する)
  72. 72. ポインタの嵌りどころ• 構文がややこしい• 多重ポインタ• constの付加
  73. 73. int main(){ int ** ppi;}このpは*演算子が2つ指定されている。これはどんなオブジェクトか。次のように書きなおしてみる。
  74. 74. int main(){ typedef int * IntPointer; IntPointer * ppi;}ppiの型はIntPointer型のオブジェクトへのポインタだとわかる。ということは、変数ppiは、IntPointer型(= int *型)のオブジェクトのアドレスを保持できるということ。
  75. 75. int main(){ int *pi; int **ppi; ppi = &pi; //int *型の変数のアドレスを //ppiに代入できる。}
  76. 76. int main(){ int **ppi = get_some_pointer();! int *pi = *ppi;! //間接参照するとアドレスの先の! //int *型のオブジェクトが返る! int i = *pi;! //もう一度間接参照するとアドレスの先の! //int型のオブジェクトが返る! int i = **ppi; //2重に間接参照できる} 注) ppi, *ppiに有効なオブジェクトへのアドレスが代入されていなければ 上記のコードは未定義動作を起こし、アクセス違反などでクラッシュする。
  77. 77. ポインタの嵌りどころ• 構文がややこしい• 多重ポインタ• constの付加
  78. 78. まずconstについて • 変数をreadonlyにする仕組みint main(){ int const value = get_some_value(); //型にconstを後置する value = 0; //コンパイルエラー}
  79. 79. まずconstについて • 変数をreadonlyにする仕組みint main(){ const int value = get_some_value(); //constを型に前置する流儀もある value = 0; //コンパイルエラー}
  80. 80. ポインタとconst• ポインタのconst性には2種類の 状況がある• ポインタというオブジェクト 自体のconst性• ポインタが指すオブジェクト へのconst性
  81. 81. ポインタとconst • ポインタというオブジェクト 自体のconst性int main(){! int i = 3;! int j = 3;! int * const pi = &i; //piに変数iのアドレスを設定! pi = &j; //コンパイルエラー。! //piの値は変更できない。}
  82. 82. ポインタとconst • ポインタが指すオブジェクト へのconst性int main(){! int i = 3;!! int const * pi = &i;! *pi = 4; //コンパイルエラー。! //constなオブジェクトは変更できない。}
  83. 83. ポインタとconst • この2つの状況を考慮すると、T * p;T * const p;T const * p;T const * const p; この4種類のconst性が異なる ポインタが宣言できる。
  84. 84. ポインタとconst • ここでT型のポインタとconst性をtypedef T * TPointer;typedef T const TConst;typedef TConst * TConstPointer; 上記のようなtypedefした名前で考 えてみると
  85. 85. ポインタとconst • 宣言はこのようになるTPointer p;TConstPointer p;TPointer const p;TConstPointer const p;
  86. 86. ポインタとconstTPointer p; • 変数pはTPointer型のオブジェクト • p自体はconstなオブジェクトではない。 よって、pの値(保持するアドレス)は変更で きる。 • *pで取得されるオブジェクトの型は、 TPointer(= T *)の間接参照なのでT。 よって、*pで取得できるオブジェクトの値は 変更できる。
  87. 87. ポインタとconstTConstPointer p; • 変数pはTConstPointer型のオブジェクト • p自体はconstなオブジェクトではない。 よって、pの値(保持するアドレス)は変更で きる。 • *pで取得されるオブジェクトの型は、 TConstPointer(= T const *)の間接参照なので TConst。よって、*pで取得できるオブジェク トの値は変更できない。
  88. 88. ポインタとconstTPointer const p; • 変数pはTPointer型のconstなオブジェクト • p自体はconstなオブジェクトである。 よって、pの値(保持するアドレス)は変更で きない。 • *pで取得されるオブジェクトの型は、 TPointer(= T *)の間接参照なのでT。 よって、*pで取得できるオブジェクトの値は 変更できる。
  89. 89. ポインタとconstTConstPointer const p; • 変数pはTConstPointer型のconstなオブジェクト • p自体はconstなオブジェクトである。 よって、pの値(保持するアドレス)は変更で きない。 • *pで取得されるオブジェクトの型は、 TConstPointer(= T const *)の間接参照なので TConst。よって、*pで取得できるオブジェク トの値は変更できない。
  90. 90. ポインタとconst• ポインタのconst性まとめ • ポインタ自体がconstか • ポインタの指すオブジェクトが constか• この二つの組み合わせ
  91. 91. 第三部ポインタを使わない
  92. 92. ポインタの問題点• 自由に制御でき過ぎる • 容易に無効な状態にできる• 指しているオブジェクトを管理 していない
  93. 93. ポインタの問題点• 自由に制御でき過ぎる • 容易に無効な状態にできる• 指しているオブジェクトを管理 していない
  94. 94. //整数の除算をおこなう関数void divide( int dividend, int divisor, int *quotient, int *remainder ){ *quotient = dividend / divisor; *remainder = dividend % divisor;}
  95. 95. int main(){ int quotient; //余りは使わなくていいから //nullptr指定しちゃえ☆ divide(8, 4, &quotient, nullptr); std::cout! << "8 / 4 = " << quotient! << std::endl;}
  96. 96. int main() { int quotient; //余りは使わなくていいから //nullptr指定しちゃえ☆ divide(8, 4, &quotient, nullptr);quotientとremainder両方とも指定して欲しいのに、 std::cout ! << "8 / 4 = " << quotient利用者がnullptrや無効なアドレスを渡せてしまう。 ! << std::endl; }
  97. 97. int main(){ int quotient; //余りは使わなくていいから //nullptr指定しちゃえ☆ divide(8, 4, &quotient, nullptr);関数divideの中でnullptrへの書き込みが std::cout! << "8 / 4 = " << quotient発生し、プログラムがクラッシュする。! << std::endl;}
  98. 98. 参照• C++で導入された、無効値を 取らずに何らかのオブジェクト を指す仕組み。• ポインタ的な性質を持ちつつ、 普通の変数のような構文で使用 できる。
  99. 99. 参照• ポインタよりもできることが 制限されているため、より安全 に使用できる。
  100. 100. int main(){ int i = 1; int &ri = i; //参照の定義と初期化 //参照は必ずなんらかの //参照元となるオブジェクトを指定して //初期化されなければならない。 ri = 2; //参照への代入 assert(i == 2);}
  101. 101. int main(){ int i = 1; int &ri = i; //参照の定義と初期化 //参照は必ずなんらかの //参照元となるオブジェクトを指定して //初期化されなければならない。 ri = 2; //参照への代入 assert(i == 2);}
  102. 102. //整数の除算をおこなう関数//引数の型を参照にしたvoid divide( int dividend, int divisor, int &quotient, int &remainder ){ quotient = dividend / divisor; remainder = dividend % divisor; //参照変数へは普通の変数と同じように //アクセスできる。}
  103. 103. int main(){ int quotient; int remainder; //参照引数を取る関数の呼び出し時に //オブジェクトを渡す。 divide(8, 4, quotient, remainder); std::cout! << "8 / 4 = " << quotient! << std::endl;}
  104. 104. int main(){ int quotient; int remainder; //nullptrのような無効なオブジェクトは //表現できないようになっている //以下はコンパイルエラー divide(8, 4, quotient, nullptr); std::cout! << "8 / 4 = " << quotient! << std::endl;}
  105. 105. ポインタの参照• ポインタもアドレスを保持する ためのただのオブジェクトなの で、ポインタの参照というもの も考えられる。
  106. 106. void delete_and_set_null(int *& i){ delete i; i = nullptr;}int main(){ int *pi = new int (); *pi = 1; delete_and_set_null(pi);! //関数にポインタを参照で渡して、! //値をdeleteしたあとヌルポインタを代入! assert(pi == nullptr);}
  107. 107. ポインタの参照• 関数の引数にポインタの参照を 受け渡した時の働きは、C#で 言うところのrefキーワードを 使用したオブジェクトの受け 渡しに近い。
  108. 108. ポインタの問題点• 自由に制御でき過ぎる • 容易に無効な状態にできる• 指しているオブジェクトを管理 していない
  109. 109. オブジェクトの所有権• ポインタはアドレスを保持して いるだけで、その先にあるオブ ジェクトの寿命は管理していな い。
  110. 110. オブジェクトの所有権• ダングリングポインタ• メモリリーク
  111. 111. ダングリングポインタ• オブジェクトが破棄されたのに ポインタのアドレスがそのまま• そのポインタを間接参照すると• 無効なオブジェクトへの アクセスとなる
  112. 112. void foo(){ Data *d = new Data(); d->getSomeValue(); delete d; //僕「先に綺麗にしておこう」 //...その他雑多な処理が沢山 //...その他雑多な処理が沢山 //...その他雑多な処理が沢山 d->getSomeAnotherValue();! //僕「最後にあれをやっておこう」} 一度解放した領域を間接参照しようとした
  113. 113. void foo(){ Data *d = new Data(); d->getSomeValue(); delete d; //僕「先に綺麗にしておこう」 //...その他雑多な処理が沢山 //...その他雑多な処理が沢山 //...その他雑多な処理が沢山 delete d; //僕「関数から抜けるので! //ちゃんと後片付けしておこう」}一度解放した領域をもう一度解放しようとした
  114. 114. void foo(){ Data *d = new Data(); d->getSomeValue(); delete d; //僕「先に綺麗にしておこう」 //...その他雑多な処理が沢山 ダングリングポインタ //...その他雑多な処理が沢山 //...その他雑多な処理が沢山 delete d; //僕「関数から抜けるので! //ちゃんと後片付けしておこう」}一度解放した領域をもう一度解放しようとした
  115. 115. メモリーリーク• newで動的にメモリを確保し生成 したオブジェクトのアドレスを 紛失し、解放できなくなってし まうこと。
  116. 116. void foo(){ Data *d = new Data(); d->foo(); return; //おっと!delete d;を忘れている。}このまま関数を抜けてしまうと、dのアドレスは誰も知らなくなる。dのアドレスの位置にあるオブジェクトはどうなる?
  117. 117. void foo(){ Data *d = new Data(); d->foo(); return; //おっと!delete d;を忘れている。}C++にはGCが無いため、newで確保されたメモリ領域は、正しく解放しなければ、プログラム終了時までメモリ上に残ってしまう。
  118. 118. void foo(){ Data *d = new Data(); d->foo(); return; //おっと!delete d;を忘れている。} メモリーリークC++にはGCが無いため、newで確保されたメモリ領域は、正しく解放しなければ、プログラム終了時までメモリ上に残ってしまう。
  119. 119. ポインタでメモリ管理• C言語では、free後にポインタを NULLで初期化して、ポインタが 無効であることを明示するのが 一般的なメモリ管理の手法。• プログラマが常に明示的にポイ ンタの有効性を意識する
  120. 120. ポインタでメモリ管理• 一方C++は スマートポインタを 使った
  121. 121. スマートポインタ• ポインタをラップしつつ、 あたかもポインタのように扱え るようにしたクラス• ポインタが指すオブジェクトの 所有権を適切に管理できる
  122. 122. int main(){ { std::unique_ptr<Data> data( new Data() ); data->doSomething(); }}
  123. 123. int main() { { std::unique_ptr<Data> data( new Data() ); data->doSomething();std::unique_ptrクラスのコンストラクタに、 } }newで生成したオブジェクトのポインタを渡す。以降は変数dataが、newで生成したオブジェクトを管理する。
  124. 124. int main(){ { std::unique_ptr<Data> data( new Data() ); data->doSomething(); }}変数dataはポインタのように扱える
  125. 125. int main(){ { std::unique_ptr<Data> data( new Data() ); data->doSomething(); } //ここでdeleteが呼ばれる}スマートポインタの変数の寿命(この例だとスコープを抜ける時)で自動的に管理しているオブジェクトがdeleteされる。
  126. 126. int main(){ { std::unique_ptr<Data> data( new Data() ); data->doSomething();このように、オブジェクトの寿命によって } //ここでdeleteが呼ばれるリソース管理を行う手法を}RAII(Resource Acquisition Is Initialization)という。
  127. 127. スマートポインタ• RAIIによって、newで作成したオ ブジェクトを変数の寿命として 管理できる。
  128. 128. スマートポインタ• RAIIによって、newで作成したオ ブジェクトを変数の寿命として 管理できる。• 例外安全性も高まる。• Exceptional C++• 「例外安全入門」
  129. 129. int main(){ std::unique_ptr<int> pi(new int()); *pi = 1; pi.reset(new int()); //新しいオブジェクトをセット //先に管理していた方は自動でdeleteされる pi.reset(); //スマートポインタを初期化! //管理しているオブジェクトは! //自動でdeleteされる}
  130. 130. int main(){ std::unique_ptr<int> pi(new int()); *pi = 1; pi.reset(new int()); //新しいオブジェクトをセットnewとdeleteと常に明示的に対応させて管理しな //先に管理していた方は自動でdeleteされるくてもよくなる。 pi.reset(); //スマートポインタを初期化! //管理しているオブジェクトは! //自動でdeleteされる}
  131. 131. スマートポインタ• 生のポインタより高機能 • カスタムデリータ • オブジェクトが破棄されるときに行われ る処理を指定できる。
  132. 132. スマートポインタ• 生のポインタより高機能 • スマートポインタはその種類 ごとに異なる特徴
  133. 133. スマートポインタ• std::unique_ptr • コピー不可/ムーブ可 • newで作成したオブジェクトは ただひとつのunique_ptrクラスのインスタン スだけで管理される
  134. 134. スマートポインタ• std::shared_ptr • コピー可/ムーブ可 • newで作成したオブジェクトは 複数のshared_ptrのインスタンスから共有さ れる。
  135. 135. スマートポインタ• boost::scoped_ptr • コピー不可/ムーブ不可 • newで作成したオブジェクトは 一つのscoped_ptrのインスタンスで管理さ れ、そのインスタンスがスコープから抜け るときに破棄される。
  136. 136. スマートポインタ• 生のポインタより高機能 • スマートポインタはその種類 ごとに異なる特徴• これらを使い分けることで、 コードの意味をより明示でき る。
  137. 137. まとめ• ポインタの構文をおさらい
  138. 138. 擬似コード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる IntPointer pi = addressof(i);! ! //piの値は0x7fff5fbfea54 indirect(pi) = 3; ! //piに代入されているアドレス経由で ! //その位置にあるint型のオブジェクトを //操作する! ! assert(i == 3): }
  139. 139. 実際のコード int main() { int i; //例えば変数iのオブジェクトは //0x7fff5fbfea54にいる int * pi = &i;! ! //piの値は0x7fff5fbfea54 *pi = 3; ! //piに代入されているアドレス経由で ! //その位置にあるint型のオブジェクトを //操作する! ! assert(i == 3): }
  140. 140. 実際のコード int main() { int i; //例えば変数iのオブジェクトは 宣言 //0x7fff5fbfea54にいる int * pi = &i;! ! //piの値は0x7fff5fbfea54 address-of *pi = 3; ! //piに代入されているアドレス経由で 間接参照 ! //その位置にあるint型のオブジェクトを //操作する! ! assert(i == 3): }
  141. 141. まとめ• ポインタの構文をおさらい• スマートポインタを使おう。
  142. 142. まとめ• ポインタの構文をおさらい• スマートポインタを使おう。 • メモリ管理の煩わしさを軽減す る。• コードの意味を明確にする。
  143. 143. その他ポインタと絡む話• ポインタと配列• ポインタと関数• メンバ変数のメモリ管理• ポインタと継承
  144. 144. 最後にお知らせ• 「C++忘年会 2012 in 札幌」• 12/15日(土)を候補に進めてます• 興味が有る方は是非ご参加くださ い!!
  145. 145. 最後にお知らせ• 「C++忘年会 2012 in 札幌」• 12/15日(土)を候補に進めてます• 興味が有る方は是非ご参加くださ い!!

×