これらすべてが、JavaとC ++の両方で深く実装定義されていることをご理解いただければ幸いです。そうは言っても、Javaのオブジェクトモデルにはかなりのスペースが必要です。
C ++のオブジェクトは、(一般的に)必要はありません任意のメンバーが必要なものを除き、ストレージを。(ユーザー定義のすべてが参照型であるJavaとは異なり)、クライアントコードはオブジェクトを値型または参照型の両方として使用できます。つまり、オブジェクトは別のオブジェクトへのポインター/参照を格納するか、オブジェクトを直接格納できます。間接なし。virtual
メソッドがある場合は、オブジェクトごとに1つの追加ポインターが必要ですが、ポリモーフィズムなしでうまくいくように設計された便利なクラスがかなりあり、これは必要ありません。GCメタデータもオブジェクトごとのロックもありません。したがって、class IntWrapper { int x; public: IntWrapper(int); ... };
オブジェクトはプレーンint
s よりも多くのスペースを必要とせず、コレクション(および間接オブジェクトなし)に直接配置できます。
配列は、C ++のJava配列に相当する既成の一般的なものがないため、トリッキーです。new[]
(オーバーヘッド/メタデータがまったくない)のオブジェクトの束を単に割り当てることができますが、長さフィールドはありません-実装はおそらく1つを格納しますが、アクセスできません。std::vector
動的配列であるため、追加のオーバーヘッドとより大きなインターフェイスがあります。std::array
およびCスタイルの配列(int arr[N];
)、コンパイル時の定数が必要です。理論的には、オブジェクトのストレージと長さの単一の整数だけにする必要があります-ただし、動的なサイズ変更と十分な機能を備えたインターフェイスを追加スペースがほとんどないので、実際にはそれで十分です。これらすべてと他のすべてのコレクションは、デフォルトでオブジェクトを値で格納するため、間接参照と参照用のスペースが節約され、キャッシュの動作が向上することに注意してください。間接参照を取得するには、ポインタ(スマートポインタを指定してください)を明示的に格納する必要があります。
上記の比較は完全に公平ではありません。これらの節約の一部は、Javaに含まれる機能を含まないことによって実現され、C ++の同等機能は、Javaの同等機能(*)よりも最適化されていないことがよくあります。virtual
C ++で実装する一般的な方法はvirtual
、Javaで実装する一般的な方法とまったく同じくらいのオーバーヘッドを課します。ロックを取得するには、完全な機能を備えたミューテックスオブジェクトが必要です。これは、数ビットよりも大きい可能性があります。(参照カウントを取得するにはありませんGCと同等であり、そのように使用すべきではありませんが、場合によっては便利です)、参照カウントフィールドを追加するスマートポインターが必要です。オブジェクトを注意深く構築しない限り、参照カウント、スマートポインターオブジェクト、および参照オブジェクトは完全に別の場所にあり、正しく構築した場合でも、共有ポインターは(1つではなく)2つである可能性があります。繰り返しになりますが、優れたC ++スタイルはこれらの機能を十分に使用しないため、問題が発生します。実際には、適切に作成されたC ++ライブラリのオブジェクトの使用量は少なくなります。これは必ずしも全体的なメモリ使用量が少ないことを意味するわけではありませんが、C ++がこの点で優れたスタートを切ることを意味します。
(*)たとえば、タイプ情報をさまざまなフラグとマージし、オブジェクトのロックビットを削除することで、仮想呼び出し、IDハッシュコード、および一部のオブジェクトの1ワードのみ(他の多くのオブジェクトの2ワード)でのロックロックが必要になることはほとんどありません。この最適化とその他の最適化の詳細な説明については、David F. Bacon、Stephen J. Fink、およびDavid Groveによる、Javaオブジェクトモデルの空間および時間効率の高い実装(PDF)を参照してください。
int
?その場合は、C ++のintが32ビットである限りint
、Java と比較する必要がありInteger
ます。