20

SO answer 1 about Heap and Stackから、疑問が生じました:変数がどこに割り当てられているかを知ることが重要なのはなぜですか?

別の回答で、誰かがスタックの方が速いと指摘しました。これが唯一の意味ですか?単純な割り当て場所の変更で問題 (パフォーマンスなど) を解決できるコード例を教えてください。

この質問は.NET固有のものであることに注意してください

1 質問は SO から削除されます。

4

7 に答える 7

18

セマンティクスが何であるかを知っている限り、スタックとヒープの唯一の結果は、スタックがオーバーフローしないようにすることと、ヒープのガベージ コレクションに関連するコストがあることに注意することです。

たとえば、JIT、新しく作成されたオブジェクトが現在のメソッドの外部で使用されていないこと (参照が他の場所でエスケープできないこと) を認識し、それをスタックに割り当てることができます。現時点ではそうしていませんが、合法的に行うことができます。

同様に、C# コンパイラはすべてのローカル変数をヒープに割り当てることを決定できます。スタックには MyMethodLocalVariables のインスタンスへの参照が含まれているだけで、すべての変数アクセスはそれを介して実装されます。(実際、デリゲートまたは反復子ブロックによってキャプチャされた変数には、既にこの種の動作があります。)

于 2009-01-25T07:40:06.613 に答える
5

(edit: My original answer contained the oversimplification "structs are allocated on the stack" and confused stack-vs-heap and value-vs-reference concerns a bit, because they are coupled in C#.)

Whether objects live on the stack or not is an implementation detail which is not very important. Jon has already explained this well. When choosing between using a class and struct, it is more important to realize that reference types work differently than value types. Take the following simple class as an example:

public class Foo
{
   public int X = 0;
}

Now consider the following code:

Foo foo = new Foo();
Foo foo2 = foo;
foo2.X = 1;

In this example, foo and foo2 are references to the same object. Setting X on foo2 will also affect foo1. If we change the Foo class to a struct then this is no longer the case. This is because structs are not accessed through references. Assigning foo2 will actually make a copy.

One of the reasons for putting stuff on the stack is that the garbage collector does not have to clean it up. You typically should not worry about such things; just use classes! Modern garbage collectors do a pretty good job. Some modern virtual machines (like java 1.6) can even determine whether it is safe to allocate objects on the stack even if they are not value types.

于 2009-01-25T03:42:03.520 に答える
4

.NET では、インスタンスを割り当てる場所を決定するのは型のユーザーではないため、議論することはほとんどありません。

参照型は常にヒープに割り当てられます。値の型は、デフォルトでスタックに割り当てられます。例外は、値の型が参照型の一部である場合です。この場合、値の型は参照型と共にヒープに割り当てられます。つまり、型の設計者がユーザーに代わってこの決定を行います。

C や C++ などの言語では、データをどこに割り当てるかをユーザーが決定できます。特殊なケースでは、ヒープから割り当てるよりもスタックから割り当てる方がはるかに高速な場合があります。

これは、C / C++ のヒープ割り当ての処理方法に関係しています。実際、ヒープの割り当ては .NET ではかなり高速です (ガベージ コレクションをトリガーする場合を除く)。そのため、どこに割り当てるかを決定できたとしても、その違いはそれほど大きくないと思います。

ただし、ヒープはガベージ コレクトされ、スタックはガベージ コレクトされないため、特定のケースでは明らかに違いが見られますが、.NET では実際に選択肢がないという事実を考えると、ほとんど関係ありません。

于 2009-01-25T13:58:28.760 に答える
3

私の意見では、スタックとヒープの違いと、それらがどのように割り当てられているかを知っていると、アプリケーションのパフォーマンスについて真剣に考え始めるときに非常に役立ちます。次の質問により、違いを理解することが不可欠になります。- スタックまたはヒープ。.NET がヒープの値型を配置できるシナリオはどれですか?

于 2011-08-11T13:45:50.823 に答える
3

最も単純な理由は、変数がヒープにある場合、不要になった変数をガベージ コレクションで処理する必要があるためだと思います。スタック上にある場合、変数は、それをインスタンス化したメソッドなど、それを使用していたものとともに破棄されます。

于 2009-01-25T03:20:23.690 に答える