文字列はスタックまたはヒープに格納されません。物語はちょっと複雑です。
リファレンスタイプのオブジェクトは常にGCヒープに格納されていると考えるのが便利です。 C++(別名std :: string)とよく似ているが、文字列のような可変長オブジェクトは、フリーストアを使って正しい量のメモリを割り当てる必要がある。 Std :: stringオブジェクト内に非常に短い文字列を格納できる、std :: string内の可能なマイクロ最適化を法とする。しかし、通常はstd :: stringオブジェクト自体をスタックに割り当てることができ、文字列がヒープに割り当てられます。 source
がスタック上にあるように、ガベージコレクタが元に戻すことができる単純なポインタです。
C言語では、文字列コンテンツをスタックに格納することができますが、必要な文字列バッファの長さを前方に推測する必要があります。何千ものマルウェア攻撃を開始すると、文字列バッファオーバーフローは、プログラムのスタックフレームを混乱させ、関数の戻り値を変更する標準的な手法です。 .NETの方法ではありません。 C言語のコンパイラでは、にはがありません。それらは非常に一般的です。
しかし、あなたが与えた例では単純ではありません。ステートメントの違いはなく、文字列の内容はスタックにもヒープにも割り当てられません。 CLRは、文字列が一致するCLR実装で動作する必要がある文字列を記述するための標準であるCLI仕様を利用するために、極小に最適化されています。
文字列オブジェクトが不変であるという性質を利用しています。これにより、というインターナショナルという最適化が可能になります。文字列オブジェクトは、GCヒープに格納されているように見え、動作します。しかし、実際にはそうではありません、オブジェクトの内容は、アセンブリのメモリマップされたイメージから直接読み取られます。アセンブリメタデータの "blob heap"に格納されます。収集中にこのような文字列オブジェクトに遭遇すると、GCはそれらを無視します。文字列リテラルがC言語でどのように動作するかと非常によく似ています。 10億のクラッシュを起こしたバグを除いて(文字列リテラルはconst char*
の代わりにchar*
)、不変性保証のために誤って文字列リテラルに書き込むことはできません。
.NETには、ヒープタイプとスタックタイプの両方があります。 – Thomas
@Matteo:C++/CLIはC++ではありません。 – Deduplicator
@Deduplicator:C++/CLIは標準C++と管理対象物を混在させることができるC++のスーパーセットです。 (私のような)C++/CLIで経験を積んだ人の多くは、C++タグに従うが、C++/CLIに従わない人が多いことを考えると、両方のタグを持つことには何の害もありません。純粋なIMOの検索で頑固にC++タグを削除するのはちょうど幼稚園です。 –