イマドキC++erのモテカワリソース管理術

download イマドキC++erのモテカワリソース管理術

If you can't read please download the document

description

7/12 プログラミング生放送+CLR/H+Sapporo.cpp 勉強会@札幌 ユビキタス協創広場 U-cala #pronamaclrhsapporocpp で発表したスライド http://pronama.azurewebsites.net/2014/06/12/pronama-clrh-sapporocpp-at-u-cala/

Transcript of イマドキC++erのモテカワリソース管理術

  • 1. 1

2. 2014/07/12 C++er @hotwatermorning C++an C++am++++ 2 3. C++ 3 4. 4 5. 5 6. 6 7. 7 8. 8 9. 9 C++er 10. 10 11. 11 12. 12 13. 13 14. 14 15. 15 16. 16 17. 17 18. 18 19. 19 20. 20 RAII RAII 21. 21 RAII RAII 22. 22 23. 23 24. CC++GC(Garbage Collection) GC : 24 25. void foo() { // int10 int* numbers = malloc( sizeof( int ) * 10 ); numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // free( numbers ); } mallocfree 25 26. void foo() { // int10 int* numbers = malloc( sizeof( int ) * 10 ); numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // free( numbers ); } // malloc // => 26 27. void foo() {// int10 int* numbers = malloc( sizeof( int ) * 10 ); numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // free( numbers ); // // => Undefined behavior numbers[0] = 101; } 27 28. void foo() {// int10 int* numbers = malloc( sizeof( int ) * 10 ); numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // free( numbers ); // // => Undefined behavior free( numbers ); } 28 29. C 29 malloc() free() 30. void readFileAndOutput() { const char* file_name = "input.txt"; // FileData* file_data = loadFileData( file_name ); for( int i = 0; i < file_data->length_; i++ ) { outputData( file_data->elements_[i] ); } // cleanupFileData( file_data ); } 30 31. // typedef struct FileData_tag { // int length_; // DataElement *elements_; } FileData; 31 32. // FileData* loadFileData( const char* file_name ) { // FileData FileData* file_data = malloc( sizeof( FileData ) ); memset( file_data, 0, sizeof( FileData ) ); // file_data parseFile( file_name, file_data ); // return file_data; } 32 33. // FileData void cleanupFileData( FileData* file_data ) { free( file_data ); } 33 loadFileData cleanupFileData 34. // FileData* loadFileData( const char* file_name ) { // FileData FileData* file_data = malloc( sizeof( FileData ) ); memset( file_data, 0, sizeof( FileData ) ); // file_data parseFile( file_name, file_data ); // return file_data; } 34 35. // void parseFile( const char* file_name, FileData* file_data) { FILE* file = fopen( file_name ); fscanf( file, "%d", &file_data->length_ ); // file_data->elements_ = malloc( sizeof( DataElement ) * file_data->length_ ); // parseElements( file, file_data->length_, file_data->elements_ ); fclose( file ); } 35 36. // void parseFile( char* file_name, FileData* file_data) { FILE* file = fopen( file_name ); fscanf( file, "%d", &file_data->length_ ); // file_data->elements_ = malloc( sizeof( DataElement ) * file_data->length_ ); // parseElements( file, file_data->length_, file_data->elements_ ); fclose( file ); } 36 37. // FileData void cleanupFileData( FileData* file_data ) { free( file_data ); } 37 file_data DataElement -> 38. // FileData void cleanupFileData( FileData* file_data ) { // if( file_data->elements_ ) { // free( file_data->elements_ ); } free( file_data ); } 38 39. 39 C GC loadFileData()cleanupFileData() 40. public static void foo() { // int[] numbers = new int[10]; numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // // // GC } Java) 40 41. 41 GC GC 42. C++ C++GCC 42 43. void foo() { // int10 int* numbers = new int[10]; numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // delete [] numbers; } C++ 43 44. void foo() { // int10 int* numbers = new int[10]; numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // => delete [] numbers; } // C C++ 44 45. C++ 45 C++ std::vector, std::list, std::deque, etc, ... 46. void foo() { // int10 // vector std::vector numbers( 10 ); numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; } // vector // vector 46 47. void foo() { // => std::vector numbers( 10 ); numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; } // => 47 48. // std::vector templateclass vector { private: T *data_; public: // vector( size_t capacity ) { data_ = new T[capacity]; } 48 49. // ~vector() { delete [] data_; } // T& operator[]( size_t index ) { return data_[index]; } }; 49 50. void foo() { // std::vector numbers; numbers.vector( 10 ); // numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; // numbers.~vector(); // } 50 51. void foo() { // int10 // vector std::vector numbers( 10 ); numbers[0] = 100; numbers[5] = 200; numbers[9] = 1000; } 51 52. C++ 52 C++ 53. 53 RAII RAII 54. 54 Mutex Socket, DB, etc, ... 55. void foo() { // std::fstream file( "output.txt" ); // file unlock(); } }; 58 59. RAII 59 idiom Resource Acquisition Is Initialization 60. RAII 60 idiom Resource Acquisition Is Initialization 61. std::mutex g_mutex; void thread_proc( AwesomeSharedData* d ) { std::lock_guard lock( g_mutex ); ModifySharedData( d ); } Mutex 61 => 62. RAII 62 Resource Acquisition Is Initialization 63. : open / close : lock / unlock : new / delete 63 64. : Exceptional C++47 (C++ in-Depth Series) 64 65. std::mutex g_mutex; void thread_proc( AwesomeSharedData* d ) { // lock()/unlock() g_mutex.lock(); ModifySharedData( d ); g_mutex.unlock(); } 65 66. std::mutex g_mutex; void thread_proc( AwesomeSharedData* d ) { // lock()/unlock() g_mutex.lock(); // ModifySharedData( d ); // g_mutex.unlock(); } 66 67. std::mutex g_mutex; void thread_proc( AwesomeSharedData* d ) { std::lock_guard lock( g_mutex ); // ModifySharedData( d ); } // `lock` // 67 RAII unlock() 68. RAII 68 69. RAII RAII http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3677.html 69 70. 70 RAII RAII 71. 71 C++RAII C++ : 72. void foo() { // std::unique_ptr p( new AwesomeClass ); // p->MemberFunction(); p->member_variable_; } 72 73. void foo() { // std::unique_ptr p( new AwesomeClass ); // p->MemberFunction(); p->member_variable_; // p // } // // delete 73 74. template class unique_ptr { private: T *p_; public: // unique_ptr( T* p ) : p_( p ) {} unique_ptr ( const unique_ptr& ) = delete; unique_ptr & operator=( const unique_ptr& ) = delete; 74 75. // ~unique_ptr() { delete p_; } // (->) // unique_ptr-> // T * operator->() { return p_; } }; 75 76. delete 76 77. void foo() { // std::unique_ptr p( new AwesomeClass ); // p->MemberFunction(); p->member_variable_; } delete 77 78. void foo() { A* p = new A; // function_may_throw( p ); // // delete p; } 78 79. void foo() { std::unique_ptr p( new A ); // function_may_throw( p ); // foo`p` // } 79 80. void foo() { A* p = new A; try { function_may_throw(); // `p` delete p; } catch( ... ) { // `p` delete p; throw; //cf, } } try-catch 80 81. void foo() { A* p = new A; try { function_may_throw(); } finally { // C++finally // delete p; } } finally 81 82. void foo() { A* p = new A; try { function_may_throw(); } finally { // C++finally // delete p; } } finally 82 C++RAII ScopeExit nally http://d.hatena.ne.jp/heisseswasser/20130508/1367988794 83. std::unique_ptr bar() { std::unique_ptr p( new B ); doSomethingWithB( p );return p; // } void baz() { std::vector> bs; for( int i = 0; i < 10; ++i ) { // bs.push_back( bar() ); } } 83 84. make_unique 84 make_unique new C++11 C+14C++11 http://stackoverow.com/questions/7038357/make-unique-and-perfect-forwarding http://herbsutter.com/gotw/_102/ 85. // // unique_ptr template std::unique_ptr make_unique() { return std::unique_ptr( new T ); } // new void foo() { std::unique_ptr p = make_unique(); } make_unique 85 86. // // unique_ptr template std::unique_ptr make_unique() { return std::unique_ptr( new T ); } // new void foo() { std::unique_ptr p = make_unique(); } make_unique 86 newdelete 87. make_unique 87 make_unique new autotype 88. void foo( std::unique_ptr pa, std::unique_ptr pb ) { //... } void bar() { // foo foo( std::unique_ptr(new A), std::unique_ptr(new B) ) } new 88 89. void foo( std::unique_ptr pa, std::unique_ptr pb ) { //... } void bar() {//new Aunique_ptr // //new B foo( std::unique_ptr(new A), std::unique_ptr(new B) ) } new 89 90. void foo( std::unique_ptr pa, std::unique_ptr pb ) { //... } void bar() { // new B // => A foo( std::unique_ptr(new A), std::unique_ptr(new B) ) } new 90 91. // // unique_ptr template std::unique_ptr make_unique() { return std::unique_ptr( new T ); } // make_uniqueunique_ptr // C++11 void foo() { auto p = make_unique(); } auto 91 92. void readFileAndOutput() { const char* file_name = "input.txt"; // std::unique_ptr file_data = loadFileData( file_name ); for( int i = 0; i < file_data->elements_; i++ ) { outputData( file_data->[i] ); } // // => } 92 93. // struct FileData { FileData() : num_data_(0) {} // int num_data_; // std::unique_ptr elements_; }; 93 94. // std::unique_ptr loadFileData( const char* file_name ) { // FileData auto file_data = std::make_unique(); // file_data parseFile( file_name, file_data.get() ); // return file_data; } 94 95. struct FCloser // { void operator()( FILE* file ) { fclose(file); } }; // void parseFile(const char* file_name, FileData*file_data) { std::unique_ptr file( fopen( file_name, "r" ) ); fscanf( file.get(), "%d", &file_data->length_ ); 95 96. // file_data->elements_ = std::make_unique( file_data->length_ ); // parseElements( file.get(), file_data->length_, file_data->elements_.get() ); } // 96 97. RAII 97 RAII 2 98. 98 RAII RAII 99. 99 100. 100 101. C# : using Java : try-with-resource Python : with Ruby : 101 102. public static void Function ( string strFilename ) { using ( StreamWriter stream = new StreamWriter ( strFilename ) ) { stream.WriteLine("Loan Pattern!"); } } C# 102 103. File::open( "output.txt", "w" ) { |f| # # f.puts "Block!" } # Ruby 103 104. Loan Pattern 104 C++ ScalaLoan Pattern Loan PatternRAII 105. RAII vs. Loan Pattern RAII RAII Loan PatternRAII 105 106. // // MyResource foo( Condition cond, Data data ) { MyResource res( getResourceHandle() ); if( cond ) { res.setStateWithData(data); else { res.setAnotherState(); } return res; } 106 107. C++Loan Pattern Loan PatternC++ http://dev.activebasic.com/egtra/2014/03/24/654/ http://carefulcode.blogspot.jp/2013/05/ri-vs-raii.html 107 108. 108 109. 109 ScopeExit D scope(exit), scope(failure) RAII Go defer 110. void abc() { Mutex m = new Mutex; lock(m); // mutex // scope(exit) unlock(m); foo(); // } scope(exit) D 110 : http://www.kmonos.net/alang/d/exception-safe.html RAII => 111. void abc() { Mutex m = new Mutex; lock(m); // mutex // scope(exit) unlock(m); foo(); // } scope(exit) D 111 : http://www.kmonos.net/alang/d/exception-safe.html scope(failure) 112. C++Scope Exit 112 Boost.ScopeExitC++ScopeExit D https://sites.google.com/site/boostjp/tips/scope_guard www.boost.org/doc/libs/release/libs/scope_exit/ 113. 113 C++ RAII RAII 114. Eective C++ 3 Exceptional C++ C++ Working Draft, Standard for Programming Language C++ N3337 http://herbsutter.com/gotw/_102/ https://sites.google.com/site/boostjp/tips/scope_guard www.boost.org/doc/libs/release/libs/scope_exit/ http://d.hatena.ne.jp/heisseswasser/20130508/1367988794 http://dev.activebasic.com/egtra/2014/03/24/654/ http://www.ne.jp/asahi/hishidama/home/tech/scala/sample/using.html http://carefulcode.blogspot.jp/2013/05/ri-vs-raii.html http://www.kmonos.net/alang/d/exception-safe.html 114