• ベストアンサー

インスタンス破棄時にメモリが解放されるようにしたい

C++言語でプログラムを作成しています あるクラスでインスタンス生成時に動的にメモリを割り当てた後 インスタンスが破棄されるまでそれを使用し インスタンス破棄時に解放するにはどうしたらいいでしょうか デストラクタで解放処理を実装すると 明示的にデストラクタが呼ばれた際に解放されてしまい インスタンスが破棄されるまで使用できませんでした

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

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

デストラクタにとって「いかなる理由で呼び出されたのか」を知る方法はありません. 従って「明示的にデストラクタを呼び出しても問題なく, かつ (スコープの外に出るなどの理由で) インスタンスを*本当に*破棄したいときには*その場で*メモリを解放する」などという都合のよい方法は存在しません. 「必要もないのに明示的にデストラクタを呼び出す」ようなやつにはちゃんとした躾をすべきなのです.

nanako_04
質問者

お礼

回答ありがとうございます 都合のよい方法はないのですね 別の対処方法を考えてみようと思います > 「必要もないのに明示的にデストラクタを呼び出す」ようなやつにはちゃんとした躾をすべきなのです. 本当にその通りだと思います ただし、躾けるべき相手がお金を払ってくれる立場にいると なかなかうまくいかないものですが、、、

その他の回答 (7)

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.8

>明示的にデストラクタが呼ばれてしまった場合でも >リカバリーできるようにしたいのです そもそも明示的にデストラクタを呼び出した後、デストラクタを含めインスタンスメソッドが正常に呼び出される保証がありませんけど。 #2で既に書いてますけど明示的にデストラクタを呼び出したことによってインスタンスの残骸にしてしまったものに、いったい何を期待してるんですか? インスタンスの残骸にインスタンスとして動くように期待しても、それは無理です。

nanako_04
質問者

お礼

回答ありがとうございます リカバリーではなく、エラーを返すようにしようと思います。

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

まず, 「明示的にデストラクタを呼び出したあとで『ふつう』に (= 『ふつうならデストラクタを実行するような方法』で) スコープ外に出る」のは未定義動作. で形のうえでは, 自動変数に対して明示的にデストラクタを呼び出したとしても placement new を使えばいけるような気はするけど, やったことないからなぁ... というか, 自動変数に明示的にデストラクタを呼び出すなんて, やろうと思ったことがないなぁ. 必要性も思い付かんし. そもそも, どうして「明示的にデストラクタを呼び出す」必要があるんでしょうか?

nanako_04
質問者

お礼

回答ありがとうございます 明示的にデストラクタを呼びだす必要があるというより 明示的にデストラクタが呼び出されることがあっても プログラムが不正な状態にならない(エラーを返すのは良い)ようにしたいのです エラーを返すだけならサンプルコードを例にすれば すべてのメソッドにおいてm_aがNULLでないことを確認すればよいかもしれませんが エラーを返さなくてよい方法を探していました

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.5

>では、明示的にデストラクタを呼んだ後 >使用したい場合はcreateなどのコンストラクタに相当するような機能を用意しておき >使用する側はそれで初期化することが必要なのでしょうか 明示的にデストラクタを呼ぶケースは、placement newを使用したときのためのものですから、#1のお礼に書いてあるようなする事が間違いです。

nanako_04
質問者

お礼

回答ありがとうございます 明示的にデストラクタが呼ばれてしまった場合でも リカバリーできるようにしたいのです

回答No.4

インスタンスが破棄される時にデストラクタが呼ばれる仕様となっています。 インスタンス破棄 と デストラクタを呼ぶ は同じ事ですね。 つまり、 「デストラクタが呼ばれた際に解放されてしまい、インスタンスが破棄されるまで使用できませんでした」 という文章は、 「インスタンスが破棄された際に解放されてしまい、インスタンスが破棄されるまで使用できませんでした」 となっていて、自明となります。 もしかして、プログラム終了まで動的に確保したメモリを使いたいということでしょうか? そうだとすれば、Formのクローズイベントなどで処理すればいいかもしれないです。 もしくは、「ある特定のインスタンスで動的に確保したメモリを他のインスタンスでも使用しているので、全ての参照がなくなったら破棄したい」という事なら、参照カウントを用意して、デストラクタが呼ばれた際にデクリメントしていって、参照が無くなった時に解法する方法も考えられます。

nanako_04
質問者

お礼

回答ありがとうございます No1のお礼に、補足としてソースコードのサンプルを記載しました

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.3

#2です。 補足しておきますが明示的にデストラクタを呼んだ場合は、インスタンスに必要なメモリが確保されてるだけの状態であってインスタンスとしては破棄済みです(だから#2では「インスタンスの残骸」と書いてる)。

nanako_04
質問者

お礼

回答ありがとうございます > インスタンスに必要なメモリが確保されてるだけの状態であってインスタンスとしては破棄済みです なるほど。 では、明示的にデストラクタを呼んだ後 使用したい場合はcreateなどのコンストラクタに相当するような機能を用意しておき 使用する側はそれで初期化することが必要なのでしょうか

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.2

デストラクタを呼び出した後のインスタンスの残骸に何を期待してるんでしょうか。

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

なにをいっているのかがわからない. 具体的にはどんなコードでどんな不具合があるの?

nanako_04
質問者

お礼

回答ありがとうございます 例えば以下のような、コンストラクタでメモリを割り当て デストラクタでメモリを解放するクラスがあるとします class Tile { public:   Tile() : m_a(NULL) { m_a = new int; }   ~Tile() { delete m_a; m_a = NULL; }   void set(int value) { *m_a = value; }   int get() const { return *m_a; } private:   int* m_a; }; このクラスのインスタンスを生成して使用する際、 明示的にデストラクタが呼び出されると、 インスタンスが破棄されていなくても使用できなくなります。 void use() {   {     Tile tile;     tile.set(10);     printf("%d\n", tile.get());     tile.~Tile(); // 明示的なデストラクタ呼び出し。     tile.set(10); // 動作しない     printf("%d\n", tile.get()); // 動作しない   } // ここでインスタンスが破棄され、2回目のデストラクタが呼び出される。 } デストラクタが呼び出された時ではなく、 インスタンスが破棄されたときにメモリを解放するにはどうしたらいいでしょうか。

関連するQ&A

  • C++でのクラスオブジェクトの破棄

    こんにちは。 C++では、プログラムの終了時に、全てのクラスオブジェクトは、デストラクタが呼び出されて破棄されますが、プログラムの途中で、クラスオブジェクトを明示的に破棄する方法はあるのでしょうか? 例えば、new演算子によってメモリを動的に割り当てたポインタなら、delete演算子で破棄できますが、 クラスオブジェクトにdelete演算子は使えないようです。 何かいい方法を知っておられる方がいらっしゃれば、是非アドバイスを頂きたいと思います。

  • メモリを解放しないとどうなる?

    趣味でプログラムの勉強をしています。 初歩的な質問になると思いますが、よろしくお願いします。 C言語やC++言語のように、動的に確保したメモリを使用後に意識して解放しないといけない言語で、解放の処理をしないままプログラム(アプリケーション)を終了した場合にはシステム(OS?)的にはどのような状態になるのでしょうか? 例: ・malloc して free しない ・new して delete しない 確保されたメモリ領域がそのまま残り、システムとして使用できるメモリ量が減る(解放にはPCの再起動が必要)のでしょうか? それともアプリケーションの終了時に自動的に解放されるのでしょうか? Windowsの場合を想定してご回答いただだけると嬉しいです。

  • C# インスタンスの破棄

    C#でインスタンスの破棄を明示的に行いたいのですが、 実際の開発現場では、どのように行っているのでしょうか? 自分で調べると「ガベージコレクタ」が暗黙的に行っているようですが明示的には行わないのが普通なのでしょうか? もしくは、「Dispose」を使用して明示的に行うのが普通なのでしょうか? 実際に開発されている方からすると簡単な事かもしれませんが教えて頂けると助かります。 以上ですが、よろしくお願いいたします。

  • インスタンス化に伴うメモリ消費への対策(メモリの解放)について

    いつもお世話になっております。 環境:PHP5,SQLite3 PHPスクリプト(1ファイル)内において、 複数のインスタンスを扱うことがあります。 つまり、スクリプトコード内に「new演算子」が複数登場するわけですが、 この際、サーバーのメモリ内に、何らかのデータが一時的に保存されるようですね? で、インスタンスを増やせば増やすほど、 そのメモリ消費量も増え、 スクリプトの処理速度に悪影響を及ぼすようなので、 これを回避するためのテクニックを教えて頂きたいなと思っております。 「インスタンスして、それが用済みになったら、削除し、メモリを解放せよ」 というようなことを、どこかで読んだことがあるのですが、 具体的には、どのような方法になりますでしょうか。 //インスタンス化 $obj = new MyClass; /* ~処理~ */ //MyClass用済み決定 unset($obj); こんな感じでしょうか? 実際的な方法について、どなたかアドバイスして下さい。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • インスタンス生成について

    いつもお世話になっております。 今回はインスタンス生成について質問させて下さい。 String クラスのインスタンス生成は、 String str1 = new String(); のように明示的に new 演算子を用いる方法と、 String str2 = "hoge"; のように生成する方法がありますよね。 str2 の方は、JVM が(?) 勝手にコンストラクタを呼び出してくれて、 インスタンスを生成してくれる、という認識でよいのでしょうか? また、明示的に「 new 演算子 + コンストラクタ」でインスタンスを生成する場合と、 そうでない場合の使い分けなどはあるのでしょうか? そもそも String 以外に、このような複数のパターンでインスタンスを生成することができる クラスは他にもあるのでしょうか? 以上、ご教授宜しくお願い致します。

    • ベストアンサー
    • Java
  • 同一クラスインスタンス名で別クラスのインスタンス作成方法(C++)

    下記ソース(Java)の処理をするような、C++の実装方法を教えていただきたいです。 【処理内容】 クラスBのインスタンスを保持しており、クラスBのインスタンス名と同一であるクラスAのインスタンス生成 ClassA A_Instance = (ClassA)Class.forName(B_instance.name).newInstance(); 要はクラスインスタンスの名前の求め方がわからないのです。それさえわかれば、newしてクラスポインタを返すメソッドを用意すれば何とかなると考えていますが。 ※C++のAPI一覧はどこにあるのだろうか・・・

  • C++のnewで確保した領域について

    こんにちわ。C++を勉強し始めた者です。 new演算子を使ってインスタンスを生成した場合、それはスタックではなくヒープ領域に確保され、不要になったらdeleteを使って領域を解放しなければいけない認識です。 C++の初心者向けサンプルコードを見ていて疑問があったので質問させてください。 (例)クラスA.cpp ======================== #include <Car> #include <Garage> ~略~ クラスAのコンストラクタ{ Car *mycar = new Car("プリウス"); addGarage( mycar ); } クラスAのデストラクタ{ } ======================== 上記のような実装のクラスAがあったのですが、コンストラクタでCarクラスのインスタンス生成をして、オート変数の*mycarに格納して、Garageの公開関数に渡しています。 質問1:このクラスAをインスタンス生成した場合、コンストラクタで確保したヒープ領域は、プログラム終了時まで解放されない認識であっていますか? 質問2:オート変数の*mycarはコンストラクタからreturnした時点で解放されてしまうので、今のままではデストラクタでヒープ領域をdeleteできない認識であっていますか? 質問3:newで生成したインスタンスへのポインタは、その関数内でdeleteしない場合、メンバ変数やstatic変数、グローバル変数に格納しなければdeleteできなくなるという理解であっていますか? 質問4:C++のコードでnewした戻り値をオート変数に格納するプログラムは通常使うことはあるのですか?

  • メモリの解放について

    メモリの解放について c#で、Mysqlへデータセットするプログラムを作っているのですが、登録する度にメモリが増加していきます。昔、VC++で同じようなプログラムを作成した時にも同現象が発生したので、SetProcessWorkingSetSize()を使って解決したのですが、c#では、解決する方法はあるのでしょうか? ご教授お願いいたします。

  • メモリ解放について

    <VC++で作成したDLLをVBで呼ぶ処理> DLL側でメモリ割り当てを行ったあと、VB側でメモリ解放を したいのですが、方法がわかりません。 教えてください。

  • マルチスレッド下でのインスタンス変数・クラス変数

    よろしくお願いします。  マルチスレッド下で動作するクラスを作成しています。データにアクセスするためのオブジェクトを クラスのフィールド値として保持し、使い回しを行いたいと考えています。このデータアクセスオブジェクト(以下Dao)内では特にフィールドは使用せず、全てローカル変数のみで動作するようになっています。Dao自体は初回のクラス生成時にstatic処理にてフィールドにセットされます。  このDaoを保持するフィールドは、staticなクラス変数が良いのか、インスタンス変数として保持する方が良いのか迷っております。  クラス変数ならばPermanent領域をオブジェクト1つ分のメモリ使用で済み、インスタンス変数だとスレッド毎にheapを使い、処理数が増えるとメモリ圧迫しちゃう?と安易に考えてしまったりしています。  ご意見・ご助言よろしくお願い致します。

    • ベストアンサー
    • Java

専門家に質問してみよう