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

このQ&Aのポイント
  • C++のnew演算子を使ってインスタンスを生成すると、確保される領域はスタックではなくヒープ領域です。不要になった場合はdeleteを使って領域を解放する必要があります。
  • 質問1:クラスAをインスタンス生成した場合、コンストラクタで確保したヒープ領域はプログラム終了時まで解放されないのでしょうか?
  • 質問2:オート変数の*mycarはコンストラクタからreturnした時点で解放されてしまうため、デストラクタでヒープ領域を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した戻り値をオート変数に格納するプログラムは通常使うことはあるのですか?

noname#255871
noname#255871

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

  • ベストアンサー
  • _kappe_
  • ベストアンサー率68% (1522/2216)
回答No.1

回答1:Carオブジェクトに対してdeleteを呼ぶコードがどこかにあってそれが実行されれば、プログラム終了前にヒープから消えます。 回答2:mycarという変数自体の領域は解放されますが、mycarが指しているオブジェクトはヒープ内に残ります。もしクラスAはCarオブジェクトへのポインタを保持せず、addGarage()によってGarageがCarオブジェクトへのポインタを保持する設計であれば、CarオブジェクトをdeleteすべきなのはGarageを削除するとき(またはGarageは使い続けるがそのCarオブジェクトは不要になった時)です。 回答3:はい。質問の例の場合はGarageがポインタを保持するのだろうと思います。クラスAで保持するようにしてもいいですが、いつ誰がCarオブジェクトをdeleteすべきなのかを設計時に明確に決めておかないと、delete済のオブジェクトに誤ってアクセスしようとする問題が生じます。 回答4:やってもいいですけれど、あまりやらないと思います。 ・その関数の中でだけそのオブジェクトを使う→ヒープ上にオブジェクトを確保したい理由が特になければnewを使わずにスタック上に確保する ・その関数から抜けた後もそのオブジェクトを使う→そのオブジェクトへのポインタをオート変数以外のどこかで保持する必要がある(その前段階で一時的にオート変数に代入することはあり得る)

noname#255871
質問者

お礼

ご回答ありがとうございました! YES/NOだけでなく詳しく教えて頂きとてもよく分かりました。

関連するQ&A

  • 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の実体はスタックではなく、ヒープ領域に確保する気がします、、 どうか、ご教授ください。

  • 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 確認方法 変数等がヒープかスタック領域のどちらに確保されたかは どうやって見分けることができますか? アドレスの値から判断できますか? よろしくお願い致します。

  • C#デストラクタが走る理由がわからない(初心者)

    WPF C# アプリを初めて組んでいます。 MainWindowクラスで、publicなクラス変数配列(myclass)を定義し、 MainWindowのコンストラクタ(もしくはLoadedイベント)で、上記クラス変数にインスタンスを生成しています。 そのインスタンスを、MainWindows内のコントロールイベント(Button_Click)で参照しようとするとNullとなっておりました。 MainWindowのコンストラクタ(もしくはLoadedイベント)完了後に、デストラクトが走っているようです。 どこからも参照されていなければGCが走りデストラクタされるのはわかるのですが、 この場合、MainWindowクラスのメンバにクラス変数を追加し、そこにインスタンスを生成しています。よって、MainWindow(つまりアプリが)が終了するまでインスタンスが参照されているため、 デストラクタが走らないのではないかと考えておりました。 ですが、上記の通り、MainWindowのコンストラクタ(もしくはLoadedイベント)後には、MyClassデストラクタが走ってしまいます。この辺を教えていただけないでしょうか。 また、下記のように、Clickでインスタンスを参照するにはどうすればよいでしょうか。 public partial class MainWindow : Window {     MYClass []myclass;     public MainWindow()     {         InitializeComponent();         //ファイル読み込み(記載省略)         for(i=0; i<ファイル読み込み数;i++)         {             myclass[i] = new myclass(ファイル読み込みデータ);         }     }     private void Button_Click(object sender, RoutedEventArgs e)     {         for(int i=0;i<myclass.Length;i++) ←ここに来る前にすでにMyClassのデストラクタが走っており、nullとなっている         {             data = myclass[i].data;         }     } }

  • newと配列?

    基本的な質問になるのですが、 例が書かれているサイトが見つからない為、質問とさせていただきたいと思います。 自分はUNIXでCの開発を行っていたのですが、C++に関してはよくわかりません。 CString a[10]; と CString a = new CString[10]; の違いを教えていただけないでしょうか? newを行い、deleteをすることで、 コンストラクタ、デストラクタを呼び出せる事はわかるのですが、 それ以外の違いはどのような点になるのですか? インスタンスについて理解できていないのでこのような 基本的な質問となりますが、ご教授願います。

  • newを使った領域の動的確保

    お世話になります。 C++での記述方法なのですが 構造体Testの領域を確保しておいて値を入れます。 確保しておいた領域では領域が不足するときに 不足分を追加したいのですがどうすればよいでしょう? Cではreallocを使えばよいと思うのですが C++ではmallocではなくnewを使ったほうがよいと聞きました。 newした領域を再定義した場合(deleteせずに領域を追加) 先に領域に入れたデータは保証されるのでしょうか? 以下例文ソース*部分 以下例文のソース Test *a; a = new TEST[10]; int cnt; int i; for(i = 0;i<10;i++){  //ここでTESTの配列aに値を入れる } cnt = 12; if( cnt > 10 ){  //予想サイズを上回ったら足りない分のサイズの領域を確保し  //データを入れる  a = new[cnt];//*ここで領域を再確保したら元のa[0]~a[9]の         //データは確実に保持されるのか?         //または他に領域を確保する方法があるのか? } 上記例文ソースでは先にcntで領域を確保すれば良いようにみえますが やりたいことは 先に確保されている領域を広げて 先に入れてあったデータと、広げた領域に入れたデータを使いたい のです。 分かりにくい文章かもしれませんがよろしくお願いします。

  • C++のstructが確保される領域について

    C++ではstructはクラスとして扱われるそうですが、 確保される領域はスタック領域だと聞きました。 StructHoge *structHoge = new StructHoge; とした場合structHogeに入っているStructHogeインスタンスのアドレスが指し示しているのは  スタック領域なのでしょうか?

  • ◆コピコンを実装しないと、returnでエラー?

    ポインタを持ったクラスで、 コピーコンストラクタを実装していないと、 newを使用した際にエラーになるそうですが、 なぜなのでしょうか? 値渡しの関数などで、 コピーコンストラクタを実装していないと、 デフォルトコピーコンストラクタで、ポインタ型のメンバ変数の値もコピーするため、 return する前に、 「一時的な変数としてコピーされていた値渡しの引数」が、 関数の終了時に解放され、 「アドレスを指しているポインタ」が指し示す先の領域に「delete」が走ってしまうため、 呼び元の変数で持っているポインタが指し示す先の領域も、 解放されてしまうとかでしょうか?? そもそも、 ポインタ pMem=NULL は、アドレスの指し示す値のリセットで、 Delete pMem は、アドレスが指し示す先頭から、そのクラスで必要としている分のメモリ量進んだアドレスまでを、解放する。 ということで合っているでしょうか? それとも、 「ポインタ」を削除しても、ポインタの指し示す先のアドレス自体は存在していて、 「呼び元」のアドレス格納用領域と、 「関数の呼び出し時にコピーコンストラクタで作られるアドレス格納用領域」は別であり、 ポインタ自体を削除しても、ポインタの先にあるメモリ領域は残っているのでしょうか?

  • クラスのインスタンス作成について

    以下のようなクラス(単純化しています)とテスト関数内でインスタンス生成しています。どちらも意味は同じですが、(1)はtest関数を抜けると勝手に消滅(デストラクタ)してくれますが、(2)はdeleteを使わないと消滅しません。 (2)の方が面倒くさい(new, delete)ですが、(2)を使わないといけない場面や理由が想像できません。クラスの配列なら意味がある???と思いますが、1つのインスタンスで(2)にする場合どんな利点があるのでしょうか? class A { }; void test{ A a; -----> (1) A *pa = new A; -+ (2) delete pa; -+ } あと、A::TEISU = 1とクラスのグローバル定数を設定したいのですがどうすればよいのでしょうか?

  • new演算子が、インスタンスの参照を返さない!?

    どうもこんにちは。 現在、iアプリ向けプログラムを作成しています。 しかし、あるクラスだけが、インスタンスを作成できない(?) ようです。 他のクラスの記述と、見比べても差がほぼありません。 コンストラクタの中に、何も書かないようにしたりしてもダメでした。 サンプルコードは、これです。 // ---------------------------------------------------------- // Window window = new Window( 10, 15+(15*6),               D.WIN_FLAG_NOCONTROL, 8, 8, 8 ); System.out.println( "エフェクト"+ new Effect() ); //つまり、コンストラクタから参照が得られないのが、問題 Effect effect = new Effect(); System.out.println("effect:"+effect); // ---------------------------------------------------------- // まとめると、Windowクラスのインスタンスは、作れるのに、 Effectクラスは、作れないという事です。 new Effect()のところで、NullPointerException例外が、発生してしまいます。 下記は、Effectクラスのコンストラクタです。 //コンストラクタ Effect() { g = MainCanvas.g; nKey = MainCanvas.nKey; } 特に変わったところは、ありません。 コンストラクタ内の二行を消しても、同じ結果でした。 もしかして、KVMが、壊れたとかでしょうか? ヒープの容量も十分にあったので、それが問題では無いと思いますが、 どうでしょうか? 見直すポイントがあれば、教えて下さい。 お願いします。

    • ベストアンサー
    • Java
  • インスタンス破棄時にメモリが解放されるようにしたい

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

専門家に質問してみよう