• 締切済み

delete について教えてください。あちこち調べてみたのですが、解決

delete について教えてください。あちこち調べてみたのですが、解決しません。 delete は、最初にその変数名で確保した領域を開放するのでしょうか、それとも現在その変数が差している領域を開放するのでしょうか? たとえば、 classe SampleClasse{ .......... }; SampleClasse *a, *b, c*; a = new SampleClasse; b = new SampleClasse; で 途中でa,bを入れ替えたとき、 c=a; a=b; b=c; delete a; というのは、現在のaの領域を開放するのでしょうか?それとも、new したときのaの領域(現在b)を開放するのでしょうか? ご教授お願いします。

みんなの回答

回答No.7

> ということは、先ほどの質問で、 > > a=new SampleClasse; > b=new SampleClasse; > > a=b; > > とした瞬間に、最初aで確保した領域は、永久に開放できないことになるのですね? > おっしゃるとおり、そのプロセスでは、aを永久に解放できません。 ただ、newで確保するのは、通常、プロセス空間のヒープ領域です。 そのためもしdeleteしなくても、プロセスが終了するとプロセス空間ごと消滅してしまうのでメモリに関する問題が生じることはありません。ただし、destructerなど適切な終了処理が実行されないことに起因する問題は生じます。(たとえば、終了処理としてプロセス間通信でどこかに通知している場合、その通知が実行されない)

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

規格上 new/delete と OS のメモリ確保/解放とは直接リンクしないことになっています (いろんな OS があるので当然といえば当然). なので, 「OS レベルでのメモリ確保/解放の動作」と「C++ のプログラムにおける new/delete の動作」とは分けて考えることができますし分けて考えた方がよいと思います. そもそも, 「new/delete が直接 OS の API をたたく」実装はそんなに多くないんじゃないかなぁ.

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.5

> a=new SampleClasse; > b=new SampleClasse; > > a=b; > > とした瞬間に、最初aで確保した領域は、永久に開放できないことになるのですね? その通りです。 まぁアプリケーション終了後ならOSの機能(ガベージコレクション)が回収してくれる事も多いですが、筋の良いプログラムではないですね。 また、C++ではこうなりますがJavaやC#などはnewで作成したオブジェクトを参照する変数がなくなったら、自動的に解放対象になります。

cometchiame
質問者

お礼

ありがとうございました。お陰さまで、関数としての動作はよくわかりました。 あとは、delete という関数(というか、メモリーを確保するという動作)が、OSレベルでどういう働きをしているかまで理解できないと完全には理解できないでしょうね。

回答No.4

newは実体を作成しますが、その返却値は実体ではなく、実体の住所(アドレス)です。 deleteに渡すのも、実体でなく、実体の住所(アドレス)です。

cometchiame
質問者

補足

みなささま、ご回答ありがとうございます。 確かに自分でも「愚問」だとは思うのですが… ということは、先ほどの質問で、 a=new SampleClasse; b=new SampleClasse; a=b; とした瞬間に、最初aで確保した領域は、永久に開放できないことになるのですね? という疑問から、ひょっとして、コンパイラーは最初のnewしたときの情報を保持していて、deleteに対してオリジナルのアドレスを渡し、最初の領域を開放してくれるのかも知れないと思った次第ですが…

  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.3

deleteのリファレンス読んでも解決しませんか? http://www.mapee.jp/cpp/delete.html デリートするのにポインタでアドレス指定しているんだから、入れ替えたらどっちが開放されるかは分かりますよね?

cometchiame
質問者

補足

ありがとうございました。 メモリーを確保するという動作が、OSレベルでどういう働きをしているかまで理解できないと完全には理解できないでしょうね。

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.2

以下を考えてみる: a = new SampleClasse; a = NULL; delete a; delete aは、newしたときの領域を解放するや否や。

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.1

「確保時の変数名」を持たない場合どうなるか、を考えればdelete時に変数の指している領域であるのは自明だと思いますが。

関連するQ&A

  • delete[]と、delete演算子の明確な違いとその使い分けについて

    C++の delete[]と、delete演算子の明確な違いとその使い分けについて 型* ptr = new 型[要素数]; でnewしたものについては、 delete[] ptr; にて、開放 型* ptr = new 型(); でnewしたものは、 delete ptr; するものだと、覚えてました、 特に深くは考えていなかったのですが。 std::auto_ptr<T> では、内部的には、delete[]ではなく deleteをしているという文章を見ました。 { std::autoptr<型A> iptr; iptr = new 型A; } のようなときは いいのですが・・・ { std::auto_ptr<char> cptr; cptr = new char[n+1]; } のようなときは、 動的配列なので、内部的に delete ptr; になってしまいます。 このように、テンプレートクラスを自作するときに 実際の特殊な型が決定されるまで、 deleteで、いくのかdelete[]でいくのか決定できないのはつらそうです。 そこで、deleteと、delete[]の正しい意味を 知りたいのですが。 Javaや、.NETには、配列オブジェクトというものが あります。 C++で、 new char[n+1]; は配列オブジェクトでしょうか? だとすると、delete[]は 右に来たものが配列オブジェクトなら、 Lengthを(こんなものがあるとして)調べて 1つづつ、まわして、deleteのほうを使ってひとつひとつ開放していく。 右に来たものが配列オブジェクトでなければ deleteと同じ振る舞いをする。 という動きが物理的に考えれそうで。 delete[]と書いておけば、状況に応じて、 動的配列なら全要素サーチして、開放そうでなければ deleteという風に、勝手に自動でそうしてくれるなら、 どんなときでも、delete[]にするようにコードを書いておけばよさそうです。。 実際のところどうなんでしょうか? deleteと、delete[]の明確な意味の違いと、 使用方法の違いについて教えてください。

  • 配列の中身のdelete

    こんにちは 配列を使った際、うまいことDeleteが働いてくれないため メモリが開放されずに困っています、 初歩的な質問で申し訳ありませんが、質問させて下さい。 下記のプログラムでは、 単純にメモリ確保とメモリ開放を行っていると思うのですが… 注釈にもあるように、Deleteでメモリが開放されません。 #include <iostream> using namespace std; class Base { }; class Sub : public Base { char size[256];//領域確保用 }; void main() { Base* obj[10000]; for(int cnt=0;cnt<10000;cnt++) { obj[cnt] = new Sub; } for(int cnt=0;cnt<10000;cnt++) { delete obj[cnt];//メモリが開放されない } } ポインタが怪しいと思うのですが、 どうにかうまいことメモリを開放することは出来ないでしょうか。 よろしければ返答お願いいたします。

  • C++ の new演算子について

    C++ の new演算子について質問です。 new演算子を用いてクラスのインスタンスを作ったときに、 クラスのメンバー関数内で使用される自動変数はメモリの何処に割り付けられますか? 以下の回答の内のいずれかと想定しています。 ・ヒープ領域 ・スタック領域 たとえば、以下のように、クラスTestClassが定義されていたとします。 class TestClass { int x; // int型(4byteとする) char y; // char型(1byte) long z; // long型(4byte) void play(short); } void main(void){ TestClass* pt = new a(); play(10); } void TestClass:: play(short n){ char a; long b; static c; for(int a = 0; a < 10; a++ ){ b = n * a; cout << b; } } main関数内で、インスタンスを作成した時点で ・TestClassのデータメンバx,y,z ⇒ ヒープ領域に確保(4+1+4 = 9byte。もしかしたらアライメント     の関係で もう少し大きく領域を確保するかも) ・play関数で使われる変数n,a,bの領域は何処に確保されるのでしょうか? 変数cは静的変数用領域に保存される? new演算子で作ったインスタンスはdelete演算子を使わないと消えないと勉強しました。(OSが消さない限り) つまり、上記ではmain関数を抜けても、変数x,y,z,n,a,bの実体は残ると考えてよいのでしょうか? そう考えると、n,a,bの実体はスタックではなく、ヒープ領域に確保する気がします、、 どうか、ご教授ください。

  • 基本クラスポインタ = new 派生クラス[i];

    基本クラスのポインタ変数pbaseを宣言し、new演算子にて派生クラスの配列を動的に確保して、pbaseに代入した場合、delete[] pbaseは上手く動作するのでしょうか。 (Aのデストラクタは仮想関数にしてあるとしておきます) ------ex-start------ class A {}; class b:public A{}; main() {   A * pbase   pbase = new B[5];   delete[] pbase } ------ex-end------ 例えば、 class Aは12バイト class Bは20バイト である場合、配列のサイズが違うのに、delete[]でちゃんと開放されるのでしょうか。 それともnew/deleteは確保したサイズをシンボル毎に記憶しているのでしょうか。 どうもこの辺が曖昧で実装する時にあやふやになってしまいます。どなたかお知恵をお貸しくださいませ。

  • 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/C++でプログラムを組んでいます。 C/C++でメモリを確保、開放するにはmalloc、new、free,deleteを使うわけですがアプリケーションが開始された時点で、ある一定のメモリを確保しておいてそのメモリから分け与えたりデフラグしたりして自分のアプリで使うメモリを管理したいと思っています。 BYTE* g_allMemory;//グローバル変数 g_allMemory = new BYTE[1024]; プログラムを実行した時点でこのようにメモリを確保しておき要所要所で自作関数を利用してメモリを分け与えたりデフラグしたりして使えるようにしたいのです。 しかしデフラグした瞬間に変数のアドレスがずれてしまって使い物になりません。 これを解決したいのですがアドバイスやお勧めのホームページや参考文献などがあったら紹介をお願いします。

  • C++で、メンバもヒープに確保されていますか

    C++でどこまでヒープに確保されるのかが分からなくなる場合があります。 特に、配列がある場合や、クラスを使う場合newしてインスタンス作って使用する場合と、 そうでない場合があり、どこまでヒープ領域に確保されているのか 分からなくなってしまっています。 (開発環境 Visual Studio 2013等) Q1 クラス内の配列 class AA{ public: int x; int dat[10]; }; AA *a0 = new AA(); とする場合と AA a1; とする場合。 このとき、メンバ変数はそれぞれ、 a0->xはヒープ領域に確保 a1.xはスタック領域に確保 されるという理解で良いですか? そして、配列a0->dat[0]等 もヒープ領域に確保されていますか? Q2 クラス内にクラス class BB{ int u,v; AA aa; }; BB *b0 = new BB(); とした場合、 b0がヒープに確保されるとして、 b0->aaはヒープに確保されており、 b0->aa.xやb0->aa.dat[0]等もヒープに確保されているという ことで良いでしょうか? Q3 確認方法 変数等がヒープかスタック領域のどちらに確保されたかは どうやって見分けることができますか? アドレスの値から判断できますか? よろしくお願い致します。

  • newで生成したものをdelete[]で破棄するのは間違い?

    int* p = new int(0); と確保したものを、普通は delete p; と書いて破棄しますが、代わりに delete[] p; と書いて破棄しても問題はないのでしょうか? 非常に悪いコードなのですが..... <1>: int* p = new int(0); <2>: int* p = new int[x]; //xはどこかで値を設定済み このうちの、1か2かのどちらかでpに対して領域を割り付けた場合に、どちらもdelete[]で破棄しても問題ないか? という意味の質問です。 コンパイルして実行しても特にエラーを吐くことはありませんでしたが非常に心配です。

  • メモリ不足になってしまう。

    教えてください。 現在陥っている現象:「メモリ不足になってしまう」配列の領域をRedimで動的に確保しようとしています。 例えば、 dim A() as byte dim B() as byte dim C() as byte redim A(8000,60000) redim B(8000,60000) redim C(8000,60000) 上記のように配列を確保する予定なのですが、 メモリ不足になってしまいます。 ひとつの変数の容量が480MB程度であると思います。 3つ全部でも1440MBであるのですが、物理的な メモリ容量は、512M*4を実装しています。 上記の変数名で言いますと、 Aの変数の領域確保には問題なく成功するのですが、 その次の行のBのところでエラーになります。 現在、物理的なメモリには空きがあるにもかかわらず このような現象になってしまい、困っています。 どなたか原因解決の糸口になるような回答をお持ちの方、 教えてください。

  • 【C++】オブジェクト配列の動的確保

    Objectがクラスとして、以下のようなプログラムを書きました Object **obj; obj = new Object*[100]; for(i=0;i<100;i++){     obj[i] = new Object(a,b,c);     obj[i]->Run();     delete obj[i]; } delete [] obj; するとdeleteの所でエラーになります。 (確保していない領域をdeleteしようとしたときのような) 何か間違っているのでしょうか。 何故かデバッガでは通ってしまいます。 環境:XP、VisualStudio2005 何卒よろしくお願いいたします。

専門家に質問してみよう