クラスのメンバ変数のnewについての例外処理とメモリリーク対策

このQ&Aのポイント
  • クラスのメンバ変数の動的割り当てで例外処理を行い、メモリリークを防止する方法について教えてください。
  • コンストラクタ内でメンバ変数に動的割り当てをする際に、例外発生時の正しい処理方法を教えてください。
  • クラスのメンバ変数の割り当てと解放において、メモリリークが起きないようにするための最適な方法は何ですか?
回答を見る
  • ベストアンサー

クラスのメンバ変数のnew

こんにちは。 クラスのメンバ変数の動的割り当てで困っていることがあります。 コンストラクタ内でメンバ変数に動的割り当てをするんですが、そこで例外処理をしなければならないようです。 例 class foo::foo() { try{ hoge = new int[100]; // hogeの代入処理 // } catch { delete[] hoge; hoge = NULL; } } foo::~foo() { delete[] hoge; hoge = NULL; } しかしこれだと不十分なようで、なかしかの対策をしないとメモリリークが起きてしまいそうなんですが どのようにやるんでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

ん~, やっぱり std::vector を使った方がいいと思うけどなぁ.... とりあえず, ここに書いてあるだけならこれでいいと思う. ここに書いてない何かがあったら知らん.

DEADSPACE566
質問者

お礼

 返答ありがとうございます。 動的確保はそれでいってみようと思います。

DEADSPACE566
質問者

補足

vectorを使ってみたところ フリーズせず正常に動作しました。 やはり動的に確保してなにかしら負担をかけていたのが原因なんじゃないか とおもいます。

その他の回答 (1)

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

う~む、前の質問 http://okwave.jp/qa/q6522287.html とあわせて考えると、 class foo { private: std::vector<int> hoge; public: foo(); }; foo::foo() { hoge.assign(100/*実際に必要な個数*/, 0/*初期値*/); // hogeの代入処理:通常の配列と同様の[]が使える // } で十分な気がするんですが……。 あるいは、 foo::foo() { hoge.reserve(100/*実際に必要な個数*/); // hogeの代入処理 for (int i = 0; i < 100/*同上*/; i++){ int value = i/*hogeのi番目の要素の値/; hoge.push_back(value); } } とするとか。

DEADSPACE566
質問者

お礼

 回答ありがとうございます。 STLのvectorを使用した場合はそうなるんですね。  例外処理自体まだ経験が浅く、メモリリークに不安があったのでこの質問をしま した。

関連するQ&A

  • Python のクラスのメンバ変数

    class foo( object ):        __result = []        def __init__( self, n, m ):       # self.__result = []       self.__result.append( n + m )    def func( self ):       print self.__result[0] hoge = foo( 1, 2 ) fuga = foo( 3, 4 ) hoge.func() # 3 fuga.func() # 3 ... !? 数値や文字列といったメンバ変数は、コンストラクタで意図的に初期化してやらなくても正常な値になりますが、それ以外のオブジェクトや配列だと fuga は hoge のメンバと同じものになってしまいます。他の言語の感覚ですと、__result は foo のメンバな上にプライベートなので、fuga の __result が hoge.__result を指すのは考えられない事なのですが、この書き方がマズいのでしょうか。 また、もしこのようになっている理由等もありましたら、併せてお教えください。

  • クラスの中にクラス

    お世話になります。 クラス1のメンバにクラス2を入れ、クラス1のコンストラクタでクラス2を操作しようとすると例外で落ちてしまいました。 しかしコンストラクタ内で別にクラス2をつくると落ちませんでした。 class Class1 {  Class2 cl2; ←クラス1のメンバにクラス2を入れる public:  Class1(); }; Class1::Class1() {  cl2.hoge(); ←落ちた  /*  ↓だと落ちなかった  Class2 _cl2;  _cl2.hoge();  */ } これは何故でしょうか? ちなみにクラスはstd::mapを使用し、hoge()はinsert_typeでした。

  • コンストラクタでnewを失敗した場合の対応について

    よろしくお願いします。 クラスのメンバで3つのlongのポインタを宣言し、 コンストラクタ内でそれぞれにnewして領域を確保 しています。 質問1)newを失敗した場合には、そのポインタに     対してdeleteしてはいけないのでしょうか? 質問2)上記3つもエリアの確保のうち、2つめで失    敗した場合、1つ目のdeleteをしてやる     必要はあるのでしょうか? catch(bad_alloc)でその処理をしようとおもうのですが、そもそもコンストラクタで例外を発生させるなと かかれている書籍もあるようです。ただ、すでにそういう記載になってしまっており、できれば、いまの構造でメモリーリークを防げないかと思案しております。どなたか、よい方法をご存知の方いらっしゃいましたら、アドバイスいただけましたら幸いでございます。

  • try~catch

    php初心者です try~catchをわかりやすく教えてください throw new Exceptionが出現したら、catchまでの処理をしないでとばすとゆうことですか? try~catchを抜けたら、他の処理は普通に実行されるのでしょうか? try~catchのカッコ{で囲む範囲は大きくしたほうがいいでしょうか?(大きく囲むと処理スピードおそくなりますか?) try { throw new Exception('エラーが発生しました');  print "hoge"; } catch (Exception $e) {  echo '例外発生', $e->getMessage(), "\n"; }  print "foo"; よろしくお願いします

    • ベストアンサー
    • PHP
  • メンバ変数が変更されそうなconstメンバ関数

    c++のconstメンバ関数についての質問です。 以下のコードの様に、constメンバ関数で メンバ変数を変更しているように見える場合、 本来はどのように記述すべきか? class foo { public: foo(){} foo(int i){ d = i; } void hoge(foo *dest0, foo *dest1 ) const { dest0->d = d*2; dest1->d = d*4; } int d; }; int main() { foo f(1); foo p,q; f.hoge(&p,&q); std::cout << f.d << "\n"; std::cout << p.d << "\n"; std::cout << q.d << "\n"; f.hoge(&f,&q); std::cout << f.d << "\n"; std::cout << q.d << "\n"; return 0; } ちなみに出力期待値は 1 2 4 2 4 とします。 上のコードは 1 2 3 2 8 と出力されますが、このようなことが無いように実装するには どうすべきかという質問です。 dest0->d = d*2; dest1->d = d*4; の所を int i=d; dest0->d = i*2; dest1->d = i*4; とすべき? それともhogeの最初に if( (this == dest0) || (this == dest1) || (dest0== dest1) ){ throw "同じオブジェクトじゃだめ"; } とすべき? どんな書き方が安定でしょうか?

  • クラスがメンバーとしてクラスを持つ時の宣言について

    自作クラスMainClassがMyClassというクラスをメンバー変数として持つ場合、宣言時に引数をいくつか持つコンストラクタを呼び出そうとすると構文エラーとなります。 class MyClass { public: MyClass(int, int); } class MainClass { private: MyClass myclass(10,10); } このような宣言はできないのでしょうか。 引数なしのコンストラクタは呼び出せているようです。

  • templateクラスについて

    先ほど以下のようなプログラムを書いたのですがコンパイルを通すことができません。 //適当なポインタを保持するだけのクラス template <class _type> class hoge { private:   //適当に変数を保持   _type val; public:   //コンストラクタで適当に値をセット   hoge() : val( 0 ){}   //このクラスから唯一ポインタを引っ張ってくる方法   friend _type getVal( const hoge& foo )   {     // そのまま返す     return foo.val;   } }; void func( const hoge<int>& foo ) {   //値を引き出す   getVal( foo ); } void main() {   //実体化   hoge<int> foo;   //値を引き出す   getVal( foo );   //関数の先で値を引き出す   func( foo ); } 上記のようなプログラムを書いたのですが、main関数内でgetValを呼び出す場合はとくに問題ないのですがfunc関数を呼び出してfunc関数内でgetValを呼び出すと error C3861: 'getVal': 識別子が見つかりませんでした error C2365: 'getVal' : 再定義; 以前の定義は '以前は不明な識別子' でした。 コンパイルされたクラスの テンプレート のインスタンス化 'hoge<_type>' の参照を確認してください というエラーが出てしまいます。 func関数の引数を( const hoge<int>& foo )からvoid func( hoge<int> foo )のように参照渡しから実体渡しに変更するとコンパイルが通り、実行もできるのですが、なぜこれでコンパイルが通るのか理由がいまいちよくわかりません。 またやはり、コンストラクタ、デストラクタの問題などから実体渡しより、参照渡しを使いたいのですがどのようにプログラムを書けば今回の問題を解決できますでしょうか。 よろしくおねがいします。 /* VisualStudio2005 AcademicEdition MicroSoft WindowsXP Professional 32bit */

  • (C++)スマートポインタをメンバ変数で使いたい

    Viual Studio 2013を使ってC++のコードを書いています。 以下のコードで、new-deleteの クラス生成をスマートポインタで置き換えたいのですが、 うまくいきません。具体的には/* not smart */の部分を スマートポインタで置き換えたいが、C2059のエラーが出てきて コンパイルできないのが理解できていません。 どなたかわかる方教えていただければ幸いです。 よろしくお願いします。 // ----コードは以下---- #include <memory> #include <iostream> class Hoge { public: Hoge(){ std::cout << "constructed!" << std::endl; }; ~Hoge(){ std::cout << "destructed!" << std::endl; }; private: }; class Hogehoge { public: Hogehoge(){}; ~Hogehoge(){ delete test; /* not smart */}; private: // error C2059 w/ VS2013 // std::unique_ptr<Hoge> test(new Hoge); Hoge* test = new Hoge; /* not smart */ }; void main() { Hogehoge foo; }

  • 参照メンバを持つクラス

    ClassAとClassBにCMyDataオブジェクトを渡したいのですが、メモリ上に同じデータのコピーを作りたくないので、コンストラクタがCMyDataの参照を受け取る設計にしました。こうすることで、CMyDataの実体はメモリ上に1つしか存在しないことになります。 ただ、クラスが、自身が管理していない外部領域にあるデータへの参照を使って仕事をするというのに違和感を感じます。 完全コンストラクタというデザインパターンがあって、クラスのインスタンスを生成する時に必要な全てのデータを渡すのが正しい流儀だそうです。 しかしこのClassA(B)の設計では、ClassA(B)の寿命が終わるまで参照先のデータが生きているとは限りません。もっといい設計はないでしょうか?ちなみにCMyDataは実際にはかなり大きなデータで、一時的であってもコピーを複数持ちたくないのです。ClassAとClassBは、実際は他のデータも参照するため1つのクラスにはしたくないのです。 class CMyData { // 色々なデータ }; class CMain { CMyData* myData; // ファイルからデータを読み込んで生成 ClassA* objA; ClassB* objB; void ReadFile() { myData = new CMyData(); // ファイルからデータを読み込みCMyData構築 } void Init() { ReadFile(); objA = new ClassA(*myData); // 自身のメンバ変数の参照でClassAを構築 objB = new ClassB(*myData); } void DoProcess() { Init(); // 実行は一度だけ objA->hoge(); // ClassAに仕事をさせる objB->foo(); // ClassBに仕事をさせる } } class ClassA { CMyData& m_data; public: ClassA(CMyData& data) m_data=data; // CMyDataオブジェクトを参照で受け取る void hoge(); } class ClassB { CMyData& m_data; public: ClassB(CMyData& data) m_data=data; // CMyDataオブジェクトを参照で受け取る void foo(); }

  • 【PHP】クラス と 関数 の違い

    class と function って具体的にはどうちがうのでしょうか。 class のメンバ変数は、 function でいうと 引数みたいな感じだし メンバ関数(メソッド?)も、function でいうと 実際の処理みたいな印象をうけます。 コンストラクターというのも、絶対的な処理 みたいな感じですが 何に使うのかよく分かりません。 class では、CSSのカスケードみたいに処理を別のclassに引き継ぎできるみたいですが、 他にどんな違いがあるのでしょうか。

    • ベストアンサー
    • PHP

専門家に質問してみよう