1

C++ では、スタック (関数内) にオブジェクトを作成し、それをヒープ割り当てコンテナー (関数に渡された/関数の終了後に存在する) に挿入するとどうなりますか?

スタック オブジェクトにはローカル スコープがありますが、スタック オブジェクトが挿入されたコンテナーはヒープ上にあり、関数 (挿入が行われた場所) が返された後も存続できます。関数が戻った後もスタック オブジェクトをコンテナから取得できますか?

void Test( std::vector<MyClass>& myvec )
{
    MyClass m;
    myvec.push_back(m);
}
4

6 に答える 6

4

この特定のケースでは、は、ベクトルによって所有されるmの新しいインスタンスにコピー構築されます。MyClassしたがって、異なるが同等のインスタンスをMyClassベクトルから取得できます。

于 2013-01-09T21:40:15.320 に答える
2
Is the stack object still retrievable from the container after the function returns?

はい、あなたmyvec.push_back(m);はmのコピーを作成し、新しいコピーはベクトルによって管理されます。

ただし、値でTest関数に渡したため、関数myvecm内部に戻った後、関数は一時的なコピーを作成してコピーし、関数が戻った後、の一時的なコピーが解放されます。したがって、以下のように参照によって関数に渡すことを意味しました。myvecTestmyvecmmyvecmyvecTest

public void Test(Vector<MyClass>& myvec){
    MyClass m;
    myvec.push_back(m);
}
于 2013-01-09T21:41:02.570 に答える
2

基本仮定: を使用する場合Vector、実際には を意味しstd::vectorます。答えは、十分に異なる設計のコンテナーで変わる可能性があります。

通常どおりにオブジェクト (ポインターではなく) をコンテナーに格納する限り、問題はありません。コンテナーに格納されるものは、通常、渡すオブジェクトのコピーであるためです。

適切な状況下では、コンテナ内のオブジェクトは渡されたものから移動構築できますが、結果は基本的に同じです。コンテナから削除されるまで (またはコンテナが破棄されるまで) 存続期間が続くオブジェクトになります。等。)

于 2013-01-09T21:42:42.277 に答える
0

関数が戻った後も、スタックオブジェクトはコンテナから取得できますか?

MyClassに「ガット」コピーコンストラクターがある場合のみ。(他のリソースの所有権のディープコピーまたは共有など)

つまり、取得することはできますが、壊れた状態になる可能性があります

于 2013-01-09T22:23:26.083 に答える
0

他の回答で指摘されているように、mベクターにコピーされます。とは言っても、関数も値によってベクトルを受け取ります (UPD: それ以降に編集された元のコードには当てはまりました)。それは明らかにあなたが望んでいたものではありません。

于 2013-01-09T21:41:51.433 に答える
0

問題のコードは、 のコピーを作成MyClassしますstd::vector。メソッドが終了すると、オリジナルmは破棄されます。Test

ポインターを格納するようにベクトルを変更する場合、MyClass2 つの選択肢があります。

void Test( std::vector<MyClass*>& myvec )
{
    // Allocates a new MyClass on the heap.
    MyClass* pM = new MyClass();
    myvec.push_back(pM);

    // This variable will be allocated on the stack and cleaned up on method exit
    MyClass dontDoThis;
    myvec.push_back(&dontDoThis);
}

このメソッドの最後には、 と のmyvec2 つの要素がmyvec[0]ありmyvec[1]ます。

ポインタのコンテナが格納されている場合、ポインタがコンテナ内にある間有効であるように、オブジェクトを割り当てる必要があります。上記の例では、ポインターはメソッドの終了pM後に有効になります。Testこれはmyvec[0]、メソッドが終了した後に有効なポインターになることを意味します。

最初に、dontDoThis変数への有効なポインターがベクターに追加されますが、メソッドが終了すると、のデストラクタdontDoThisが呼び出され、メモリはおそらく他のデータを格納するために使用されます。のポインターは問題ないようにmyvec見えますが、実際に使用しようとすると、未定義の動作が発生します。メソッド exit のポインタはmyvec[1]有効に見えるかもしれませんが、実際にはジャンクを指しています。

後でmyvec[0]が変更または削除された場合は、次のように呼び出すことが重要です。

delete myvec[0]

オブジェクトが適切にクリーンアップされるようにします。そうしないと、メモリ リークが発生します。

ネイキッド ポインターで何が起こるかを説明した後、std::unique_ptrstd::shared_ptrなどのスマート ポインターを使用することを強くお勧めします。

于 2013-01-09T22:02:25.013 に答える