3

これは本当にばかげた/基本的な質問かもしれませんが、私はそれを理解することはできません. 私の考えをお伝えします。間違っている場合は訂正してください。

生のポインタを格納するために STL コンテナを使用している場合、それらの後のクリーンアップに注意する必要があります。

std::list<animal*> alist;
animal *a = new animal();
alist.push_back(a);
...
animal *b = alist.front();
alist.pop_front();
//do stuff with b
delete b;

オブジェクトを保存するとどうなりますか? オブジェクトでいっぱいのコンテナが範囲外になると、その中のすべてのオブジェクトが破棄されることを私は理解しています。正しい?

std::list<T>.pop_front()しかし、たとえば、コンテナからオブジェクトを削除するとどうなるでしょうか?

std::list<animal> alist;
{
  animal ani();
  //ani is inserted at the end of the list (it IS ani rather than a copy 
  //since push_back accepts const T&)
  alist.push_back(ani);
} //nothing is deallocated/destroyed here
...
{
  animal b = alist.front(); //b is now a copy(?!) of the front element
                            //created via copy constructor
  alist.pop_front(); //the front element of the list is 
                     //destroyed/destructor is called 
  //do stuff with b
} //b goes out of scope
4

5 に答える 5

6

コンテナに何かを保存すると、渡したものはすべてコンテナ1にコピーされます。あなたはまだ元のオブジェクトを所有しています2 ; コンテナはオブジェクトのコピーを所有します。push_back(一例として)そのパラメータを参照によって取るのは事実です。つまり、オブジェクトをコンテナにプッシュする場合、パラメータ自体として使用するためにコピーは必要ありませんが、コンテナに入れられるのは、プッシュするように指示したもののコピーのままです。参照による受け渡しは、1つのコピーのみが必要であることを意味します。値で渡された場合(少なくともC ++ 98/03では)、2つになります。コピー:オブジェクトから関数の引数に1つコピーし、次に関数の引数からコンテナーにもう1つコピーします。参照渡しにより、元のオブジェクトから直接コンテナに直接1つのコピーを作成できます。

同様に、コンテナからオブジェクトを取得すると、コンテナに含まれていたもののコピーを取得します。コンテナにはまだオブジェクトがあり、オブジェクトがあります。これらのそれぞれには、独自の寿命があります。

コンテナからオブジェクトを消去またはポップすると、そのオブジェクトはコンテナから削除されて破棄されます。デストラクタがあるものの場合は、デストラクタが呼び出されて破棄されます。

コンテナ自体が破壊されると、コンテナ内のオブジェクトは破壊されます。あなたのオブジェクトは、それがたまたまあるときはいつでも破壊されます-それがコンテナから来たという事実はそれに影響を与えません。ローカル変数の場合、スコープ外になると破棄されます。グローバルの場合は、(プログラムの場合)時間の終わりまで続きます。関数からそれを返し、それが参照を初期化するために使用される場合、そこでの存続期間を延長するための通常の規則が守られます。結論:その時点では、それは単なる別のオブジェクトであり、同じ方法で定義された他のオブジェクトと同じように存続期間があります。

ポインタ(rawまたはsmart)をコンテナに格納する場合、これは少し...あいまいになる可能性があります。上記のすべては実際には当てはまります、コピー/保存されるオブジェクトはポインタです。ポインターを格納していることを「認識」しているコンテナー(Boost ptr_vectorなど)を使用しない限り、ポインターを処理し、ポインターが参照するオブジェクトがどこかにあるという事実を「無視」します。


  1. C ++ 11では、たとえば、emplace_backコンテナ内の所定の場所にオブジェクトを作成するために使用できますが、同じ基本的な考え方が適用されます。コンテナには所有するオブジェクトがあり、直接触れることはありません。
  2. ここでは、プログラマー以外の人が使用するように「オブジェクト」を使用しています。これは、必ずしもクラスのインスタンスではなく、「何か」を意味するためです。Cが単語を使用するという意味では、「オブジェクト」ではない場合もあります。純粋な右辺値(たとえばpush_back(10))である可能性があります。
于 2013-01-16T15:20:18.227 に答える
2
std::list<animal> alist;
// A list is created in automatic storage (the stack).  Its elements
// will exist in the free store (the heap)
{
  animal ani;
  // ani is created in automatic storage (the stack)

  alist.push_back(ani);
  // A copy of ani (using animal(const animal&) ctor) is created in
  // the list "alist" via memory allocated on the free store (the heap)

} // ani.~animal() is called, then the storage for ani is recycled
// (ie, the stack space that ani used can be reused)

{
  animal b = alist.front();
  // either animal(animal&) or animal(animal const&)
  // is called on the previous line, constructing an instance
  // of animal called "b" in automatic storage (the stack)
  // This is a copy of a copy of the animal instance called "ani"
  // above, assuming nothing else besides this code has manipulated
  // alist

  alist.pop_front();
  // The animal in the alist that is a copy of ani is destroyed
  // from the free store (the heap)


  //do stuff with b
} // b.~animal() is called, then the memory in automatic storage
// (the stack) that b lived in is recycled for other purposes
于 2013-01-16T15:22:13.867 に答える
2

はい。動的メモリを指すポインタではなくオブジェクトを格納する場合は、割り当て解除を行う必要はありません。
要素をポップするとき。標準ライブラリは、ポップされたオブジェクトのデストラクタを呼び出すように注意します。

ルールは次のとおりです。何か(呼び出され
た)を割り当てた場合は 、割り当てを解除(呼び出しdelete)する必要があります。new

于 2013-01-16T15:17:02.140 に答える
2

オブジェクトでいっぱいのコンテナがスコープから外れると、それに含まれるすべてのオブジェクトもスコープから外れると私は理解しています。正しい?

まず、いくつかの重要な衒学者。 オブジェクトはスコープ外になりませんが、識別子は外に出ます。これは重要な違いであり、ここで何が起こっているのかを明確にするのに役立つ可能性があります。

コンテナに対応する識別子(変数)がスコープ外になると、対応するオブジェクト(コンテナ自体)が自動的に削除されます。次に、そのデストラクタはその各要素を順番に削除します。

std::list<T>.pop_front()しかし、たとえば、コンテナからオブジェクトを削除するとどうなるでしょうか。

コンテナは、含まれている要素を削除するだけです(あなたが懸念している限り、コンテナはそのデストラクタを呼び出します)。(残りのすべての要素を1つずつシャッフルするなど、他のハウスキーピングもある可能性がありますstd::vector。これにより、多くのデストラクタ/コピーコンストラクタの呼び出しが発生します)。

于 2013-01-16T15:17:09.367 に答える
2

STLコンテナからオブジェクトを削除すると、そのデストラクタがstruct/class-typeの場合に呼び出されます。また、コンテナによっては、オブジェクトの格納に使用される内部データ構造も割り当て解除/破棄されます。

ポインタ型は構造体/クラス型ではないため、ポイントされているメモリを管理できるデストラクタがないことに注意してください。したがって、STLコンテナからポインタを削除するときに偶発的なメモリリークを回避したい場合はstd::shared_ptr<T>、ポインタに割り当てられたメモリを適切に管理し、ポインタへの参照がなくなったときに割り当てを解除するようなスマートポインタタイプを使用することをお勧めします。割り当てられたメモリオブジェクト。

于 2013-01-16T15:17:22.553 に答える