1. ホーム
  2. language-agnostic

[解決済み] ボクシングとアンボクシング、そのトレードオフとは?

2022-05-30 23:46:51

質問

明確、簡潔、正確な答えを求めています。

理想的には実際の回答として、良い説明へのリンクは歓迎します。

どのように解決するのですか?

ボックス化された値は データ構造 の最小限のラッパーです。 プリミティブ型 *. ボックス化された値は、通常 ヒープ .

このように、ボックス化された値はより多くのメモリを使用し、アクセスするために少なくとも2つのメモリ検索を必要とします。1つはポインタを取得するため、もう1つはそのポインタからプリミティブをたどるためです。 明らかに、これは内部ループで必要とするようなものではありません。 一方、箱型の値はシステム内の他の型との相性が良いのが一般的です。 それらは言語の第一級のデータ構造であるため、他のデータ構造が持つ期待されるメタデータと構造を持っています。

Java と Haskell では、ジェネリックコレクションはボックス化されていない値を含むことができません。 .NETのジェネリックコレクションは、ペナルティなしで非ボックス化された値を保持することができます。 Java のジェネリックがコンパイル時の型チェックにのみ使用されるのに対して、.NET は 実行時にインスタンス化された各ジェネリック型に対して特定のクラスを生成します。 .

JavaとHaskellには箱詰めされていない配列がありますが、他のコレクションに比べると明らかに利便性に欠けます。 しかし、最高のパフォーマンスが必要なとき、箱詰めと箱出しのオーバーヘッドを避けるために少し不便にする価値はあります。

* この議論では、プリミティブ値は コールスタック に格納できるもので、ヒープ上の値へのポインタとして格納されるのではありません。 よくあるのは、機械型(ints、floatなど)、構造体、そして時には静的サイズの配列です。 .NETの世界では(参照型ではなく)値型と呼ばれます。 Javaではプリミティブ型と呼ばれています。 Haskellions は単に unboxed と呼びます。

** 私はこの回答で、Java、Haskell、C#に焦点を合わせています。 参考までに、Python、Ruby、および Javascript はすべて、排他的にボックス化された値を持ちます。 これは、"Everything is an object"アプローチとしても知られています***。

*** 警告: 十分に高度なコンパイラー/JIT は、場合によっては、ソースを見たときに意味的にボックス化されている値が、実行時には安全にボックス化されていない値であることを実際に検出することができます。要するに、優秀な言語実装者のおかげで、ボックスが自由になることがあるのです。