deleteをなくすには
deleteコードを減らすことは、複雑なコードの保守やリソースリークの観点で望ましい。
下のようなコードでdeleteを消したい。
なお、new[]で確保した配列は、delete[]で削除しなければいけないことに注意。
class C { public: char* buf; unsigned int size; C( char* p, unsigned int sz ) : buf(new char[sz]), size(sz) // new[]で確保 { memcpy(buf, p, sz); }; ~C() { delete[] buf; } // delete[]で削除 }; void test_code() { vector<C> v; char* m = new char[100]; // new[]で確保 C a(m, 100); v.push_back(a); delete[] m; // delete[]で削除 }
unique_ptrを用いてみよう。unique_ptrも配列については配慮が必要だ。
代入演算子で余分な削除が起きている(reset)。
class C { public: unique_ptr<char[]> buf; unsigned int size; C( unique_ptr<char[]>& p, unsigned int sz ) : buf(move(p)), size(sz) {} C( const C& lhs ) : buf(new char[lhs.size]), size(lhs.size) { memcpy( buf.get(), lhs.buf.get(), size ); } const C& operator=( const C& lhs ) { size = lhs.size; buf.reset( new char[size] ); memcpy( buf.get(), lhs.buf.get(), size ); return *this; } ~C() {} }; void test_code() { vector<C> v; unique_ptr<char[]> m( new char[100] ); C a(m, 100); // mからaへ配列ポインターは移動する v.push_back(a); }
配列ポインターの移動のためにコンストラクターを追加したということもあるが、コード数が増えてかえってメンテがしにくいような気もする。
このような場合は素直にvectorを使えば簡易になる。
class C { public: vector<char> buf; C() : buf() {} C( vector<char> &p ) : buf(p){} ~C() {} }; void test_code() { vector<C> v; vector<char> m(100); C a(m); v.push_back(a); }
文字列であればstringを用いることもできる
class C { public: string buf; C() : buf() {} C( string &p ) : buf(p){} ~C() {} }; void test_code() { vector<C> v; string m; m.resize(100); C a(m); v.push_back(a); }