• ベストアンサー

クラスの宣言でのメモリ使用サイズの違い

お世話になります。 現在、Visual Studio 2005にてMFCのC++のプログラムを作成しているのですが、そこでメモリの使用容量について疑問に感じた点があったのでこちらで、質問させて頂きました。 お聞きしたい内容は あるクラス1内で別のクラス2を宣言する際に、メンバ変数としてそのクラス2を宣言し、クラス1のコンストラクタでnewでメモリを確保し、デスクリタでdeleteする方法と、その都度クラス2の変数または関数が必要なときにnewでメモリを確保して、deleteで開放する方法とでは、メモリの確保等で違いがなにかありますでしょうか? また、クラス2をクラス1,クラス3で使用する場合には、クラス1,クラス3でそれぞれクラス2のオブジェクトを宣言するのと、クラス1でクラス2のオブジェクトを宣言し、そのオブジェクトをクラス3でexternするのではどちらの方がメモリの使用等からよい方法なのでしょうか? 今までほとんどメモリを気にせずにプログラムを作っていた為、メモリの使用の点ではほとんど無知な為、変な質問なのかもしれませんが、ご存知の方がいらっしゃいましたら、ご回答をお願い致します。 開発環境は Widows CE 6.0 Visual Studio 2005 です。

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

その都度、オブジェクトを生成して済むのであれば、静的メンバ関数にできないか検討してみてはどうでしょうか? 静的メンバ関数にできるのであれば、オブジェクトを生成する必要がなくなりますから、メモリの使用量はゼロになります。

fujtomo
質問者

お礼

その都度クラス1,クラス3で呼ばれるクラス2の関数を静的関数にしてみたらいい、ということでしょうか? そうすれば、確かにメモリの使用はなくなりますよね。 その方法で考えてみます!!

その他の回答 (2)

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.3

>どちらの方がメモリの使用等からよい方法なのでしょうか? "等"という言葉があったのでツッコミを入れさせていただきます。 メモリの使用だけに限定されないと解釈しています。 まず、何度も何度もnewを繰り返すと”メモリの断片化(フラグメント)"が 起きる恐れがあります。 http://yougo.ascii.jp/caltar/%E3%83%95%E3%83%A9%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%88 最近のPCであればメモリを十分に積んでいるので 1) 1MByte new 2) 1MByte delete 3) 100kByte new 4) 100kByte delete 5)1MByte new 6)1Mbyte delete をするよりは 最初から1MByteをnewもしくはstaticで確保して、使いまわすほうが 好ましいと思われます。 もちろん3)と4)の間では900kByteも無駄が生じることは 百も承知ですが 2GByteの物理メモリで900kByte気にしてもしゃーない という”富豪プログラミング"です。 あと >クラス1のコンストラクタでnewでメモリを確保し、デスクリタでdeleteする方法 この場合、クラス1にクラス2の"ポインタ"をもつということになりますね >クラス1,クラス3でそれぞれクラス2のオブジェクトを宣言する この場合、クラス2のオブジェクトをクラス1(および3)が抱え込む形ですね。 この2つのパターンにはメモリ以外に重要な違いがあります。 それは前者(ポインタ)の場合は"前方宣言"で済ますことが可能ということです。 前方宣言を使うと、クラス1のコンパイルにクラス2の情報は不要になります。 クラス2の実装を変更してもクラス1はコンパイルしなおさなくて済みます。 ことは、ビルド時間の長短の問題だけではありません。 クラス2はクラス1に影響を与えず、まったく自由に変更できるということは クラス2はそれと機能面で互換性のある2aや2b...と自由に交換可能に なるのです。 これは、複雑なプログラムを組む時に非常に大きなメリットとなります。 以上、メモリの瞬間・瞬間の利用効率以外の 長期的視点からみてみました。 以上の視点とメモリを極力無駄にしない努力を 時には天秤にかけ どちらを優先するか判断してみてください。

fujtomo
質問者

お礼

丁寧なご回答ありがとうございます。 メモリのnewとdeleteを繰り返すと、フラグメントが発生するのですか。。それは初めて聞きました、参考にさせて頂きます。 ということは、その都度のメモリの使用のみを考えて、あるクラスの各関数内で、ローカル変数として、別のクラスのオブジェクトのnew.deleteを繰り返してメモリを確保するよりも、長期的にみてあるクラスのグローバル変数として他のクラスのオブジェクトを宣言し、コンストラクタでnew,デストラクタでdelteした方がよいとも考えられるということですね。 また、教えて頂いたクラスのオブジェクトの前者、後者の違いですが、あるクラスで別のクラスのオブジェクトを宣言するときは、ポインタとして呼び出す方が、利便性があるということですね。 ご回答ありがとうございます。

回答No.1

クラスのインスタンスがメモリー上に実在するのは クラスのコンストラクタが実行されてインスタンス が生成されてから、そのインスタンスがデストラクタで 破棄されるまでで、これをクラスの寿命といいます。 つまり生きているクラスは全てメモリ上に存在するわけです。 以上の理屈より、ご質問の件は自明ですね(^^)/。

fujtomo
質問者

お礼

ということはクラス1のメンバ変数にクラス2のインスタンスを指定し、クラス1のコンストラクタでnewでメモリを確保すると、クラス1のデストラクタが呼ばれるまで常にクラス2のインスタンス分のメモリが確保され続けてしまうということですね? 逆に、その都度new,deleteを呼ぶことでインスタンス分のメモリの確保・開放を繰り返しているということですか。 だとしたら、面倒でも何度も繰り返しインスタンスを作成したほうがメモリの面ではいいということですね。

関連するQ&A

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

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

  • クラスでnew宣言

    いつも御世話になっています。 クラス作成時に、 オブジェクト型(クラス型)を変数として宣言している時がある気がするのですが、ClassB classB = new ClassB(); この場合の利点は何かあるのでしょうか? 普通に考えれば、この記述を宣言することで、この宣言がされているクラス自身が、ClassBの実体を持つことになり、このクラスだけで多数のクラスの実体を利用できるようになる。 と思ったのですが。 クラスとしては、 ClassA { private ClassB classB = new ClassB(); } という場合です。 ここで、private ClassB classB;でない理由: むやみに、上記の書き方をすると、外部から書き換えられてしまう恐れがあるから、、なるべくその可能性を回避するため 宜しくお願いします。

    • ベストアンサー
    • Java
  • クラスメンバをnewで宣言できますか?

    こんにちは。 教えていただきたいのですが、クラスメンバ(変数)を動的に確保することは できるのでしょうか?(一応やってみたのですが、エラーになってしまいました。) それから、Newでの二次元配列の確保は、どうやったらよいのでしょうか? ヘルプでもうまく探せません。 よろしくお願いします。

  • visual c++ のグローバル変数宣言について

    visual c++で、 例えば下記のようにグローバル変数宣言するが 下記プログラムの「FileMei1[0][n1] = 0;」のところでブレークをかけてプログラムを走らせると、ウォッチウィンドウで「FileMei1エラー: 識別子 'FileMei1' はスコープ外です」とでてきます。 グローバル変数宣言のやり方間違っているのでしょうか? namespace TestCpp { extern char FileMei1[300][100]={ 0 }; public void aa{ for(n1=0; n1 < 100 ; n1++) { FileMei1[0][n1] = 0; } }

  • 基本クラスポインタ = 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は確保したサイズをシンボル毎に記憶しているのでしょうか。 どうもこの辺が曖昧で実装する時にあやふやになってしまいます。どなたかお知恵をお貸しくださいませ。

  • 変数の宣言方法の相違によるエラー

    ある変数を関数内で宣言した場合、デバック時に「ハンドルされていない例外が発生しました」っていうエラーになります。でも、グローバル変数として宣言した場合には、同じエラーが発生しませんでした。今回の場合、配列を10,000,000ぐらい確保しようとしたので、メモリ領域を確保できなかったが、エラーの発生原因だと思います。メンバ変数とグローバル変数で確保できるメモリ領域にどれくらいの違いがありますか。その他にクラスのメンバ変数として宣言した場合とグローバル変数として宣言した場合でどのような違いがありますか。 わかる方が教えてください。よろしくお願いします。

  • VBAで宣言セクションにクラスの宣言をしたい

    Excel VBAについての質問です。 ClassDataBaseというクラスモジュールを作成し、それをSheet1やThisWorkbookの宣言セクションで Public DB As New ClassDataBase というように宣言しようとしました。 ですが、これだと ---------------------------------------------------------- コンパイルエラー プライベートオブジェクトモジュールを、パブリックオブジェクトモジュール内で、パブリックプロシージャの引数または戻り値、パブリックデータメンバ、またはパブリックのユーザー定義型フィールドとして、使用することはできません。 ---------------------------------------------------------- というエラーが出てしまいます。 実は以前に質問し、教えていただいた際には標準モジュールで宣言するようにとのことだったのですが、他ではできないのかな?と思い、試したところこのような結果になってしまいました。 エラーの意味がわかればよかったのですが、ヘルプもなく、意味もわかりませんでした・・・。 どなたか、ご教授いただければ幸いです。 よろしくお願いいたします。

  • delete演算子によるメモリ解放について

    MFC MDIプログラミングで、 Genericクラスで点、線、面クラスを作って、 オブジェクトを組み合わせて 3次元図形を作っています。 図形を削除する際、 delete演算子で各オブジェクトの メモリ解放をプログラムしています。 例) delete m_pLine; delete m_pSurface; しかしながら、これらポインタの中には、 アルゴリズム上、既にdeleteされているものもあるため、 既にdeleteしたオブジェクトを更に deleteしようとして 実行時エラーを生じてしまいます。 deleteする前に、 当該ポインタが既にdeleteされているかどうか 判定する関数等あれば if文で回避できると思うのですが、 何か良い方法がありますでしょうか? よろしくお願いします。

  • 自アプリ内のメモリを管理したい

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

  • クラスを使ったC++の関数をCで呼び出すには?

     QNo.152285と類似の質問になりますが、独自に用意したクラスを内部で使用し、extern "C" を宣言した、C++の関数をCプログラムから呼び出し、Cコンパイラでリンクすることを考えています。  この場合、C++関数内で使用されるクラスについても、extern "C"の記述が必要でしょうか?  またその記述の仕方はどのようになるでしょうか?  あるいは、そういったことはできないのでしょうか?(coutが使えることを考えると、できないわけではないとも思っていますが)  あるいは、コンパイルの際の、オプションなどで解決できるでしょうか?  クラスはnewで生成して使用しています。 環境はソラリスのCCとccを使っています。 どうか、ご回答よろしくお願いします。