質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

Q&A

解決済

5回答

23283閲覧

C++でのクラスのメンバ関数が占める容量が知りたい

himagin57

総合スコア13

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

1グッド

1クリップ

投稿2015/11/18 11:14

編集2015/11/18 11:15

C++で大量のクラスの配列を使わなくてはならないのですが、メモリをどれくらい食うのかが気になりました。
sizeof()で調べてみたのですが、50行ほどの関数のみのクラスが1Byteとのことでした。
これだけの命令を記録するのに必要な容量が1Byteとはどうにも信じられません。本当に関数は容量をほとんどとらないのでしょうか?それともsizeof()では確認できないようなところでメモリを食っているのでしょうか?

rocket👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

検索して見つけた参考になりそうな記事をご紹介させていただきます。

http://www.libjingu.jp/trans/bs_faq2-j.html

C++は不勉強なので見当違いかもしれませんが、上のリンクの

C++のオブジェクトはメモリ上でどのように配置されるのですか

空のクラスのサイズが0にならないのはなぜですか

という項目が、sizeof()関数の実行結果の説明になるかと思います。

また、

本当に関数は容量をほとんどとらないのでしょうか?

に関しては、以下のリンクを見つけました。
http://stackoverflow.com/questions/3888069/memory-allocation-for-member-functions-in-c
http://stackoverflow.com/questions/9683095/memory-static-function-vs-member-function

公式の説明ではないので本当かどうかは分かりませんが、
1つ目のリンクに

All instances share the same member function code.

と、2つ目のリンクに

(Virtual functions will typically add the size of one pointer to the class,

とあります。

要するに、virtualでないメソッドのメモリは、インスタンスのメモリ空間とは別の(つまり、sizeof()関数に影響しない)場所に展開されており、メンバーメソッドであってもその実体は1つだけのようです。

投稿2015/11/18 12:23

KiyoshiMotoki

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

メンバー関数の実体はプログラム・コードです。main()関数等のグローバル関数と同様、実体は「コード」が記録される領域に記録されます。この領域の使用サイズはsizeof()演算子でカウントされません。そのクラスのインスタンスをいくらたくさん作っても、メンバー関数の実体が占める領域サイズは増えませんので。

メンバー変数は、データ領域に記録されます。この領域の使用サイズがsizeof()演算子で返却されます。

メンバー変数が1つもない場合、sizeof()の結果は0でもよいと思いますが、1バイトの領域を占めることが多いと聞きます。たぶん、サイズが0だとメモリを割り当てられないので、そのインスタンスへのポインタを作れない等不都合があるからと思います。

後、仮想関数等は、その関数のコードがあるアドレスへのポインタが記録されます。見えない関数ポインタがあると思えばよいです。これはインスタンス内に記録されるのでsizeof()演算子でカウントされます。

投稿2015/11/18 12:35

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C++のクラスのメモリサイズは、メンバ変数の合計値となります。
sizeof識別子で計ったクラスには、char型のメンバ変数のみだったのではないでしょうか?
コンパイラの境界値の設定によっては、4バイト区切りだったり、8バイト区切りだったりしますが、基本的にすべてメンバ変数のみがメモリサイズに影響します。

投稿2015/11/18 11:35

shanxia

総合スコア1038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

himagin57

2015/11/18 11:47

メンバ変数は1つもありませんでした。試しにint型の変数を1つメンバ変数に加えて5Byteになるか試しましたが、4Byteのままでした。理由はわかりません。 重ねて申し訳ありませんが、それなら関数はどこに保存されているのでしょうか? どこか一か所に保存されていて、クラスがそれを呼び出しているのでしょうか?
shanxia

2015/11/18 13:31

既に他の方の回答に書かれているとおり、メンバー変数を持つデータ領域と、メソッドのコード領域は別々に保持されます。 これはC++のコンパイル時に、アセンブルコードを出してみると、よりわかりやすいと思います。 クラスオブジェクトのメモリサイズには、データ領域のサイズのみが影響すると言うことになります。
catsforepaw

2015/11/18 22:14

横から失礼します。 メンバ変数のない(あるいは空っぽの)クラスのsizeofが0ではなく1を返す理由についてですが、それは、そういう仕様だからです。 オブジェクトとして存在させるにはアドレスを与える必要があり、アドレスを与えるからには別のオブジェクトと区別できるように異なるアドレスにしなければならず、そのためには(使わないけど)1バイトの領域を確保してやらないといけないのです。 例えばこんな時 ```C++ class Hoge{}; // 空のクラス Hoge a[2]; Hoge *p0 = &a[0]; Hoge *p1 = &a[1]; ``` p0とp1が別のアドレスになることが保証されるというわけです。
shanxia

2015/11/18 23:54

そうだったんですか。 知りませんでした。指摘ありがとうございます。
guest

0

C++に限らず他の多くの言語もそうですが、メモリといっても、データを置く場所とコードを置く場所が分かれています。

「コード」はプログラムの実行命令のことで、関数の中身はそこに納められます。
sizeof()で調べられるのはデータのサイズなので、コードのサイズを求めることはできません。

では関数の中身はどこに行ったかというと、「実行ファイル(exeやdllファイル)の中」にあります。ですから、50行のプログラムと5万行のプログラムでは、実行ファイルのサイズが大きく違ってきます。

投稿2015/11/18 12:48

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

himagin57

2015/11/19 09:47

皆さんありがとうございました。 関数は変数とは別の場所に、クラスオブジェクトの占める容量とは無関係に保存されるのですね。 これで関数を大量にクラスに入れることにためらいがなくなりました。
guest

0

VSは知らないのですが・・・、実行ファイルのアセンブラソースが出力できるのでしょうか?
出力出来ればサイズの算出は出来ると思いますが・・・

bsdにはobjdumpというプログラムがあってそれで実行ファイルを見るといかのように出力されます。

a.out: file format elf64-x86-64-freebsd

Disassembly of section .init:

000000000000b4e8 <.init>:
400be8: 48 83 ec 08 sub $0x8,%rsp
400bec: e8 6f 03 00 00 callq 400f60 <_Unwind_Resume@plt+0x234>
400bf1: e8 ca 06 00 00 callq 4012c0 <_Unwind_Resume@plt+0x594>
400bf6: 48 83 c4 08 add $0x8,%rsp
400bfa: c3 retq
Disassembly of section .plt:

0000000000400bfc atexit@plt-0x10:
400bfc: ff 35 96 0b 20 00 pushq 0x200b96(%rip) # 601798 <_Unwind_Resume@p

中略

4012f8: 48 83 ec 08 sub $0x8,%rsp
4012fc: e8 1f fc ff ff callq 400f20 <_Unwind_Resume@plt+0x1f4>
401301: 48 83 c4 08 add $0x8,%rsp
401305: c3 retq

こうすると401306-400be8->71e(十進で1822バイト)あることが分かります。

・・・追記・・・
ちなみにソースは

C++

1~/test >cat hw.cpp 2#include <iostream> 3 4using namespace std; 5 6int main() 7{ 8 cout << "hollow word!" << endl; 9 10 return 0; 11} 12 13~/test >コード

投稿2015/11/18 12:37

編集2015/11/18 12:46
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問