2017-10-08 6 views
1

私はスタックがどのように動作し、変数が動かされたときに何が起こるかを理解していると思いますが、私はこの質問に対する答えを見つけることができません。私は説明しましょう:変数を外側のスコープに移動するとき、スタックにはどうなりますか?

新しいスコープが入力/作成されると、スタックの上に一定量のメモリが取得されます。スタックポインタはこのメモリを指します。スタックの現在のサイズを表します。スコープが残っていると、スタックポインタが元の位置に戻ることでメモリが解放されます。

C++ 11以降のセマンティクスを移動すると、一部のデータの所有権を変数間で移動できます。これにより、データを保持するメモリが同じままであるため、データのコピーが回避されます。移動後、移動先変数はメモリ内のデータの位置を指し、移動元変数は基本的にヌルポインタになります。ここでは、移動セマンティクスをポインタにあまりにも近づけて関連させることで、私の最初の間違いを作っているかもしれません。私ですか?

実際の質問: 変数は内部スコープ内に作成され、外部スコープ内の変数に移動されます。次に、内部スコープが終了します。スタックはどうなりますか?

与えられていると、スタックポインタは元の位置に戻り、内側のスコープメモリを解放する必要があります。しかし、内部スコープからのメモリはまだ有効です。外部スコープ変数にアタッチされているためです。外部(おそらくグローバル)スコープと以前の内部スコープメモリの間にブロックされた/無駄なメモリがたくさんあるかもしれません。外部スコープが終了すると、このメモリは再び使用可能になります。これまではスタックのサイズが膨らんでいました。これは本当ですか?これは避けられますか?コンパイラはこれを防ぐのですか?私はあなたの混乱を理解すると思う

+0

「移動セマンティクス」は、オブジェクトが物理的に別の場所に移動したことを意味しません。これは、あるオブジェクト(例えば、オブジェクトがポインタを保持するヒープ上に割り当てられたメモリのチャンク)によって管理される状態が、そのオブジェクトのクラスによって指定された方法で他のオブジェクトに渡されることを意味します。その状態を完全にコピーします。これは、スタック上であろうとなかろうと、これらのオブジェクトによって占有されるメモリがどのように割り当てられ、解放されるかには決して影響しません。 –

+0

それが私の要点です。占有メモリは移動後も同じままですが、スタックが正常に機能するためには、スコープが残っているときにスコープのすべてのメモリを解放する必要があります。たぶん私はそれをはっきりと説明しなかったかもしれない。 – bjoern

+0

移動セマンティクスは、ヒープへのポインタを持っているクラス(あなたが気にしなければならない限り)でのみ役に立ちます。ディープコピーではなく、ヒープデータの所有権があなただけであることが分かっているので、クラスを浅くコピーすることができます。以前の所有権はあなたに「移動」されました。したがって、 'move'が実際にスタックに置かれていないときに気にするメモリです。スタックオブジェクト(ヒープメモリへのポインタを持つクラス項目)はまだコピーされますが、ヒープ内のすべてのデータのディープコピーと比較して小さく、許容範囲です。 – Troyseph

答えて

0

免責事項、素人の観点から、危険なアナロジーとフォローする不安定なC++の知識...

[stack frame a] 
std::vector toPopulate; 
    [stack frame b] 
    std::vector toMove; // will be std::moved into `toPopulate` somehow 

スタック範囲はbを離れ、戻っaに戻り、 moveはスタックフレームにメモリを残すことはできませんので、どのようにコピーを防止するのですかb ...

回答:それはありません! toMoveのスタックデータはtoPopulateにコピーされ、std::vectorはその内容をスタックに格納せず、メモリがヒープ内のどこにアドレス/ポインタを格納するだけです。ここで何をしているかstd::move

vectorに言っているの深い(ヒープ内の別の場所にヒープデータをコピーしない)自分自身をコピーしない、ちょうどdataポインタをコピーし、私を信頼し、これはやっても安全ですコンパイル時に安全性が強制されます。

したがってtoPopulateが構築され、そのdataCountとdataPointer、およびstd :: vectorを記述するために必要なものはすべてヒープメモリに書き込まれますが、ヒープデータには触れられず、複数のstd::vectorsをスタックに入れると、実際には面倒です!

+0

これは意味があり、スタックのサイズに関する私の別の混乱を解消します。 STLコンテナは決してスタックに格納されませんか? letだけがベクタまたはマップのメタデータをスタックに呼び出すだけですか?それはすばやくコピーされ、実際に解放されます。そして、スタックに何十何百または何百MBのサイズのベクトルを格納できる理由を説明します。これは正しいです? – bjoern

+0

まさに、私はほとんどのSTLコンテナがこのように動作すると思います。 – Troyseph

関連する問題