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

このQ&Aのポイント
  • C++のnew演算子を使用したクラスのインスタンス作成時に、自動変数はヒープ領域に割り付けられますか?
  • インスタンスを作成した時点で、TestClassのデータメンバx, y, zはヒープ領域に確保されます。
  • play関数で使われる変数n, a, bはどこに確保されるでしょうか?変数cは静的変数用領域に保存されます。
回答を見る
  • ベストアンサー

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

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

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

Cで書いたなら struct TestClass { int x;// int型(4byteとする) char y;// char型(1byte) long z;// long型(4byte) } void TestClass__play(struct TestClass * This, short n) ; void main(void){ struct TestClass* pt = malloc(sizeof(struct TestCalss)); TestClass__play(pt, 10); } void TestClass__play(struct TestClass * This, short n){ char a; long b; static c; for( a = 0; a < 10; a++ ){ b = n * a; printf("%ld", b) ; } } 細かい違いはあるけど、あながちハズレではないはす。 こうすれでば、メンバ関数がどう実装されているか、メンバ関数で使用するローカル変数がどこに確保されるのが妥当か、わかるのではないでしょうか?

beam_mea
質問者

補足

お礼が大変遅くなりました。申し訳ありません。 おっしゃるとおり、メンバ関数で使用するローカル変数はスタックに詰まれると考えるのが妥当でした。 どうしても、自分の目で確かめたくなって、 Runesas製マイコンRX用の統合開発環境CubeSuite+でビルドをし、動かしながら、何処に領域を確保するのかを確認してみました。 結果、newしたオブジェクトもメンバ関数内のローカル変数の領域は、スタックに確保していました。 また、クラスのサイズをsizeof演算子で出したところ、以下のように面白い結果になりました。 1.メンバ変数をもつクラスのサイズ⇒メンバ変数の数×4byte 2.メンバ関数しかない(メンバ変数が無い)クラスのサイズ⇒1byte 1番は納得できますが、2番は何故1byteと思いました。 実際は、2番のケースでnewした際、1byte分ヒープ領域に確保するものの、中身は0のまま何も使用されていませんでした。 Tacosanさんのおっしゃる通り、処理系によって変わるので、これが全てではないでしょうが、大変勉強になりました。 ありがとうございました。

その他の回答 (4)

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

>new演算子で、作ったインスタンスはどの時点で消えるのでしょうか? delete演算子で消したとき。 またOSがインスタンスを削除することはありません。 正確にいえばインスタンスとして削除しないだけで、ヒープとしてはOSに帰りますが。 >「関数を抜けてしまえば不要になる」理由を教えて頂けないでしょうか。 関数内だけで使用する変数が関数抜けて必要になる場面てあるんですか?

beam_mea
質問者

補足

回答ありがとうございます。 > 関数内だけで使用する変数が関数抜けて必要になる場面てあるんですか? 大前提が頭から抜けていました。 おっしゃるとおり、自動変数のスコープは{}内ですね > またOSがインスタンスを削除することはありません。 > 正確にいえばインスタンスとして削除しないだけで、ヒープとしてはOSに帰り> > ますが。 勉強になります。

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

クラスのメンバー関数も、通常の関数も、同じ関数です。 メンバー変数が使えるとか言った機能以外の違いはありません。 ありがちな実装では > ・TestClassのデータメンバx,y,z ⇒ ヒープ領域に確保(4+1+4 = 9byte。もしかしたらアライメントの関係でもう少し大きく領域を確保するかも) メンバー関数へのポインタが加わるケースもあります。 決めつけないで、必要なときはsizeofで確認を。 > ・play関数で使われる変数n,a,bの領域は何処に確保されるのでしょうか? > 変数cは静的変数用領域に保存される? 通常の関数と同じで ・引数はスタックに積まれる ・自動変数はスタック領域に確保される ・static変数はstaticな領域に確保される

beam_mea
質問者

補足

回答、ありがとうございます。 new演算子で、作ったインスタンスはどの時点で消えるのでしょうか? 上記の場合、main関数を抜けたときにポインタ変数ptが指しているオブジェクトは必ず消えるといえるでしょうか?  消える場合 ⇒ C言語で使う関数と同様に考えれば良いので、 play関数内の自動変数a,bはスタックに確保されるかと思います。  消えない場合 ⇒ もし、main関数を抜けてもオブジェクトは残るのであれば、   play関数内の自動変数a,bは、後入れ先出しであるスタックではなく、   ヒープ領域に確保するのではないかと考えております。 上記の場合、ポインタ変数が自動変数なので、 main関数を抜けたときに、オブジェクトも消してもらったほうが 安全だと思いました。 > メンバー関数へのポインタが加わるケースもあります。 > 決めつけないで、必要なときはsizeofで確認を。 コンパイラによって、変わってくるのですね。 勉強になりました。

回答No.2

> クラスのメンバー関数内で使用される自動変数はメモリの何処に割り付けられますか? ほとんどのコンパイラでは「スタック」に置かれます。 関数を抜けてしまえば不要になるので。

beam_mea
質問者

補足

早々の回答ありがとうございます。 「関数を抜けてしまえば不要になる」理由を教えて頂けないでしょうか。

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

規格上何も決まっていません.

beam_mea
質問者

補足

早々の回答ありがとうございます。

関連するQ&A

  • 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++でどこまでヒープに確保されるのかが分からなくなる場合があります。 特に、配列がある場合や、クラスを使う場合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++のnew演算子について質問です。

    C++のnew演算子について質問です。 以下は関数にポインタを渡して値を得ようしたプログラムです。 ※ディレクティブは省略しています。 void test( int* a ) { a = new int( 100 ); } void main() { int* b; test(b); printf( "%d", *b ); delete b; b = NULL; } このプログラムを実行すると、コンソール画面には100と表示されるかと思っていたのですが、 実際には滅茶苦茶な値と、例外が発生して強制終了しました。 また、関数に渡したポインタのアドレスもNULLとなってしまいます。 そこで以下のようにソースを変更すると正常に100が表示されました。 void test( int** a ) { *a = new int( 100 ); } void main() { int* b; test(&b); printf( "%d", *b ); delete b; b = NULL; } 結果的には目的が達成できたのでいいのですが、なぜこのような動作をするのかが いまいち釈然としません。 new演算子は自動的には破棄されないのではないのでしょうか? 回答の程、よろしくお願いします。

  • new演算子

    1:new演算子は2次元配列はつくれますか?? 2:new演算子で配列を動的に生成して以下の文字を代  入したい場合はどうすればいいですか?    char* a = new char[3]; a[] = {"ABC" "EFG" "HIJ"}    上のプログラムだと、a[0]にABCの文字が入りませ  ん。どうすれば、a[0]にABCを格納できますか?

  • c++のnew演算子をオーバーロードできるものの、

    c++のnew演算子をオーバーロードできるものの、 delete演算子をオーバーロードできなくて悩んでいます。 コンパイルは通るのですが、ランタイム時に ペアとなるdeleteが呼ばれません。 inline void* operator new(size_t size, const char* filename , int line , const char* funcname ) { return my_local_malloc( size , filename , line , funcname ); } inline void operator delete(void* pMem, const char* filename , int line , const char* funcname ) { my_local_free( pMem , filename , line , funcname ); } deleteも確実にオーバーロードできる方法を ご存知のかた、お教え願います。

  • new領域確保について

    お世話になります new演算子の使用方法について教えてください。 new演算子は、動的確保を行なう際に使用する事は知っております。 もう1つの使用理由として、関数内のローカル変数領域が多大になる場合に 使用すると聞いた事があります これは、スタック領域を圧迫しないためと説明を受けた記憶があります これがあってるとしたら、どれくらいの変数容量を宣言する際に、new演算子を使用するのでしょうか? よろしくお願い致します

  • new演算子と初期化子 { } の違いについて教えて下さい

    演算子と初期化子 { } の違いがわからなくて調べています。 // newを使った配列 int[] a = new int[3]; a[0] = 1; a[1] = 2; a[2] = 3; // { } を使った配列 int[] a = { 1, 2, 3 }; /* 上記の例は配列ですが、 例えば、配列ではない、Kamokuというクラスを作ったときに、 { } でコンストラクタを使用して、インスタンスを作ることは不可能ですか?メモリは確保しないのでしょうか?

    • ベストアンサー
    • Java
  • C++のnewの使い道

    最近C++を勉強しているのですが、new演算子はどういうときに使うべきでしょうか? メモリを動的確保できるのはわかります。 Cのmallocのようなものと考えていいのでしょうか? つまり、関数内でメモリを確保してそのアドレスを返すとか、コンパイル時に不明なサイズのメモリを実行時に確保するとか、任意のタイミングでメモリを開放したい場合などに使うものでしょうか。 ある参考書を読んでいると「引数つきコンストラクタを呼び出す場合はnewでインスタンス生成する」と書いてありました。 デフォルトコントラスタならnewなし、引数付きならnewあり、ということらしいです。 なぜこんなことをする必要があるのでしょうか?

  • C++のnew演算子で動的確保

    new()を初めて使ってみました。 エラーは無かったけど、間違いがあったら教えてください。 #include <iostream.h> main(){ int n = 0; char* str = "mojisuufumei"; char* myValue; while(!str[n])n++; myValue = new char[n+1]; strcpy(myValue, str); cout << myValue; delete []myValue; } char*型のmyValueを動的確保したつもりです。 myValue[0], myValue[1], … のそれぞれの値を unsignedにして宣言したい場合はどうしたらいいんですか? #include <iostream.h> main(){ int n = 0; char* str = "mojisuufumei"; unsigned char* myValue; while(!str[n])n++; myValue = new unsigned char[n+1]; strcpy(myValue, str); cout << myValue; delete []myValue; } だと、strcpy()のとこでコンパイルエラーでした。

  • new演算子のオーバーロードについて

    #include <stdio.h> #include <windows.h> class MyNew { public: void* ptr; MyNew( void* p ) { ptr = p; } void* MyNew::operator new( size_t size ) { printf("new-\n"); return malloc( size ); } void MyNew::operator delete( void* ptr ) { printf("delete-\n"); free( ptr ); } }; void main( void ) { MyNew p = new int; } クラスのメモリ確保をnew演算子のオーバーロードを用いて書いてみたのですがオーバーロードしたnew演算子が呼ばれません。 なぜでしょうか? /** VisualStdio2005コンソールアプリケーション WindowsXP */

専門家に質問してみよう