Astruct
は、スタックに割り当てられる場合と割り当てられない場合があります。参照型をスタックに割り当てることはできません。それらは常にヒープに割り当てられます。
標準 (ISO 23270)、§ 8.8 から:
8.8
構造体 クラスと構造体の類似点のリストは長く、構造体はインターフェースを実装でき、クラスと同じ種類のメンバーを持つことができます。ただし、構造体はいくつかの重要な点でクラスと異なります。構造体は参照型ではなく値型であり、構造体では継承がサポートされていません。構造体の値は「スタック上」または「インライン」に格納されます。注意深いプログラマーは、構造体を適切に使用することでパフォーマンスを向上させることができます。
たとえば、 Point のクラスではなく構造体を使用すると、実行時に実行されるメモリ割り当ての数に大きな違いが生じる可能性があります。以下のプログラムは、100 ポイントの配列を作成して初期化します。
クラスとして実装するとPoint
、101 個の個別のオブジェクトがインスタンス化されます。1 つは配列用で、1 つは 100 個の要素用です。
class Point
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
class Test
{
static void Main()
{
Point[] points = new Point[100];
for (int i = 0; i < 100; i++)
{
points[i] = new Point(i, i*i);
}
}
IfPoint
は、代わりに構造体として実装されます。
struct Point
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
インスタンス化されるオブジェクトは 1 つだけです。つまり、配列用のオブジェクトです。Point インスタンスは、配列内でインラインで割り当てられます。この最適化は悪用される可能性があります。クラスの代わりに構造体を使用すると、アプリケーションの実行が遅くなったり、メモリの消費量が増えたりする可能性があります。構造体インスタンスを値で渡すと、その構造体のコピーが作成されるためです。
したがって、答えは「たぶん」です。
あなたの例では、配列(参照型)をstruct
(値型)内にラップしても意味がありません。その配列はまだヒープに割り当てられています。
ただし、クラスEdgeData
を構造体に変更すると、配列内でインラインに割り当てることができます (ただし、割り当てられない場合があります)。EdgeData
たとえば、クラスのサイズが 16 バイトで、100 個のエントリを作成して入力すると、実際には 1 つの配列インスタンスが割り当てられます (100 個のオブジェクト参照とクラスEdgeData[]
の 100 個の個々のインスタンスを保持するサイズのバッキング ストアを使用)。EdgeData
.
が構造体の場合EdgeData
、100 個のEdgeData
インスタンスを保持するサイズのバッキング ストアを含む 1 つの配列を割り当てます (この場合、架空のEdgeData
構造体のサイズは 16 バイトであるため、1600 バイトです)。
EdgeData
配列のクラス バージョンを反復すると、特に配列が非常に大きい場合、ページングが発生する可能性があります。これは、ヒープ全体をジャンプして個々のインスタンスにヒットするため、おそらく参照の局所性が失われるためです。
インスタンスがインラインであるため、配列のバージョンを反復処理すると、struct
参照の局所性が保持されます。EdgeData