• 締切済み

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

みんなの回答

noname#203932
noname#203932
回答No.5

自動変数はスタックから、newした場合はヒープからなんでしょけど、実際は最適化されて全然違う動きしてることもありますよ。 デバッグモードとリリースモードでも、メモリの取り方は変わってきますよ。 参考までに

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.4

ヒープやスタックかの話をするときは機器とOSと開発環境を限定してもらわないと回答が難しいと思って下さい。C/C++の規格外の話なので環境依存するとしか言えないのです。 開発環境 Visual Studio をVisualStudioに限定し、OSをWindows、機器をx84/x64アーキテクチャと言うことでよろしいですか? そうするとautoなローカル変数はスタック上であると考えてもらえば良いと思います。ただし、スタックサイズはビルド時に変更できるので多少の融通は効きます。が、普通はこんなことはしません。ギリギリまで使ったら安全マージンがなくなりますから。 ローカル変数的なクラスのインスタンスも同様です。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

> a0->xはヒープ領域に確保 > a1.xはスタック領域に確保 分けて考えているのが混乱の元。 メンバ変数は、クラスの一部です。 クラスがどうやって確保されたかを考えれば、メンバ変数がどこに確保されいるか、すぐわかるのでは。 int a[5] ; とは、 sizeof(int) * 5 分の一塊の領域を「int が5つの配列」として使うためのもの。 class AA{ public: int x; int dat[10]; }; というのは、 sizeof(int)の一塊の領域とsizeof(int)*10の一塊の領域を含む、全体でsizeof(AA)の一塊の領域を使うためのものです。 > AA *a0 = new AA(); は、自動変数用の領域にsizeof(AA*)の一塊の領域が確保され、変数a0 という名前でアクセスできるようになります。 その内容は、 new AA()でnew/delete用の領域に確保された(そしてコンストラクタで初期化された)領域へのポインタになります。 > AA a1; は、自動変数用の領域に sizeof(AA)の一塊の領域が確保され、変数a1 という名前でアクセスできるようになります。 その内容は、(コンストラクタで初期化された)AAです。 > BB *b0 = new BB(); > とした場合、 > b0がヒープに確保される ポインタの場合は混同しないようにしましょう。 変数b0 自体は、自動のポインタ変数です。 自動変数用の領域にsizeof(BB*)の一塊の領域が確保されています。 その内容が new BB()で確保した領域のアドレスになっているのです。 BB b1 ; *b0=&b1 ; とすれば、 b0は b1のアドレス(=自動変数用の領域)になります。 ------------ スタック、ヒープというのは、実装方法の一つであって、C++で決められたものではありません。 http://www.uquest.co.jp/embedded/learning/lecture42.html > ヒープメモリについては、mallocなどのメモリ割り当て関数が、 > 開発環境(コンパイラ)に付属する標準ライブラリでサポートされている場合もあるんだけど、 > ない場合は自分で作る必要がある。 とあるように、mallocが「ヒープ」を使うとは限りません。 また、スタックオーバーフローは、スタックを使い過ぎたときに出るものです。 ですが、Windowsのような余裕のあるシステムでは、そうそう出るものではありません。 ・大きな配列やクラスを自動変数として宣言しない ・再帰関数の呼び出しの深さに注意して、深くなりすぎないようにする というのに気をつければ、まず発生することはありません。

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

C++ の規格 (とりあえず手元にある 14882:1998) に出てくる「スタック」や「ヒープ」って ・例外処理における専門用語としての「stack unwinding」と関連用語 ・std::stack や優先準位キューがらみ (<algorithm> の std::make_heap など) しかないんだよね. さて, あなたの使ってる「スタック」とか「ヒープ」ってのは, これのことでいい?

supercaram
質問者

補足

プログラムのメモリ配置でいう、スタックメモリとヒープメモリのことです。 「newやmallocを使うとヒープに確保される」というときに使う、ヒープメモリのことです。 ここに解説されている通りの内容です。 http://www.uquest.co.jp/embedded/learning/lecture42.html

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.1

>C++でどこまでヒープに確保されるのかが分からなくなる場合があります。 それを分かる必要がありますか? C++の仕様としてはヒープとスタックの使い分けに関して何にも定義はありませんけど。

supercaram
質問者

補足

分かる必要あります。 考慮しないでスタックを使いすぎるとスタックオーバーフローになってしまいます。

関連する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++の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++のstructが確保される領域について

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

  • 配列の数を途中で増やすには?

    はじめまして。 この度、以下のようなプログラムを作りました。 が、途中で配列の数を増やすことになってしまいました。 ------------------------------------------------ struct a{ int int_a; long int_b; }; struct b{ a *aa; }; void main(void){ b *bb; bb = new b[3]; bb[0].aa = new a[5]; bb[1].aa = new a[4]; . . . } ------------------------------------------------ 具体的には、'bb'の配列を3から5に増やすようなやり方を探しています。 元の配列より大きい配列をつくり、そこにコピーすればいいと考えたのですが、 'bb'内の'aa'の配列も動的に作成しているため、それも出来ない状況です。 どなたかやり方を知っている方がいましたら、教えていただきたいです。 下手な説明ですいません。

  • C++で領域の確保の方法

    今C++の勉強中なのですが、 領域の確保の方法でいい方法が知りたいのです。 ポインターのポインターを使って二次元配列の領域を確保したいのですがいい方法が思いつきません。 int **pBox; pBox = new int *[ 10 ]; for( int i=0; i<10; i++ ) { pBox[ i ] = new int[10]; } //ちなみに今はこんな感じのものしか考え付きませんint型[10][10] を確保したつもりです。 間違っていたら教えていただきたいです。 本題はこちらで、もっと効率のいい確保の方法を知りたいのでご協力を よろしくお願いします。

  • 構造体の配列とメンバの配列

    typedef struct _ex_table1 {   int  x[10];   int  y[10]; }ETable1; ETable1 et1; int ans1; for( int a = 0; a < 10; a++ ){   et1.x[a] = a+10;   et1.y[a] = a*2; } for( int b = 0; b < 10; b++ ){   if( et1.x[b] == 15 ){     ans1 = et1.y[b];     break;   }   else{     ans1 = 0;   } } printf( "%d", ans1 ); ///////////////////////////////// typedef struct _ex_table2 {   int xx;   int yy; }ETable2; ETable2 et2[10]; int ans2; for( int aa = 0; aa < 10; aa++ ){   et2[aa].xx = aa+10;   et2[aa].yy = aa*2; } for( int bb = 0; bb < 10; bb++){   if( et2[bb].xx == 15 ){     ans2 = et2[bb].yy;     break;   }   else   {     ans2 = 0;   } } printf("%d", ans2 ); と言う感じに、微妙にソースを書いてみたのですが、 上のメンバ(x,xx)の値が正しいものがあったら、 対応する下のメンバ(y,yy)を出力したいと思っていますが、 構造体を配列にした場合と、構造体メンバを配列にした場合は どのように違うのでしょうか? 私には、同じように思えてしまいます。 どなたか、利点・欠点など教えていただけませんか? よろしくお願い致します。

  • ヒープの探索の再帰

    A[N]を利用したヒープのプログラムを作りました。 A[i]の親は、A[(i-1)/2]であるヒープです。 (上に行くほど小さい整数を格納) そしていまある整列されたヒープのなかからキーボードから入力した値xを検索する関数findを、 x ←検索する値 A[]←ヒープソートされた配列 n ←格納されているA[]の最後の添え字 として、 int find(int x, int *A, int i, int n) { if(A[i]==x){ printf("*\n"); /* ここの作業が行われているかを確認 */ return 1; } if(i>n)return 0; if(A[i]>x){ return 0; } else if (A[i]<x){ i = 2*i + 1; find(x, A, i, n); i++; find(x, A, i, n); } return 0; } というものを作ってみました。汚いかもしれませんが、とりあえず今はこれでいっぱいいっぱいです。 それで、当然のごとくうまくいきませんでした。 /**/内に書いたように、入力したxがヒープ内にある場合は「*」が一応表示されるのですが、どうもfindは1を返してくれません。0を返してしまいます。見つけた後もまだ再帰をくりかえしえしているようです。 どこがいけないのでしょうか。

  • C/C++言語のメモリについて

    C言語でメモリを2種類?に分けると、スタックとヒープがあります。 ヒープは mallocなどで確保し、freeで解放しますがスタックは解放する必要がありません。 そのスタックは通常、何バイトまで可能なのでしょうか? あと関数外のファイルの先頭に int[1000000];とした場合、このメモリはmallocで確保していませんが、 どこに作られるのでしょうか? 私のパソコンはメモリが2GBでWindows2000ですが、CやC++で最大、何バイトまでメモリが使えますか? また、一番多くメモリを確保できるなら、OSはなんでも構いません。 解釈等も間違っていたらご指摘していただきたいです。

  • 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言語におけるローカル変数が使用するメモリについて

    例のようなC言語のプログラムを動かした場合、 確保されるメモリ領域はどうなるのでしょうか。 例 #include <stdio.h> int main(void) { int a = 0; } このとき、変数aはint型なのでスタック領域に4バイトのメモリが確保されると理解しています。 と同時にaという変数名と確保されたスタック領域の番地を紐づけるようなメモリがどこかに確保されるのではないかと思ってるのですが、この理解で正しいでしょうか。 またその場合は変数aの番地はどの領域に確保されるのでしょうか。 ご教示お願いいたします。

専門家に質問してみよう