web-dev-qa-db-ja.com

ベクトル、ポインター、およびC ++デストラクタ

私の知る限り、デストラクタでnewで作成したものをすべて破棄し、開いているファイルストリームやその他のストリームを閉じます。ただし、C++の他のオブジェクトについては疑問があります。

  • std::vectorおよびstd::strings:それらは自動的に破壊されますか?

  • 私のようなものがあれば

    std::vector<myClass*> 
    

    クラスへのポインタの。ベクトルデストラクタが呼び出されるとどうなりますか?
    myClassのデストラクタを自動的に呼び出しますか?または、ベクトルのみが破壊されますが、それに含まれるすべてのオブジェクトはまだメモリ内に存在しますか?

  • クラス内に別のクラスへのポインタがある場合、どうなりますか?

    class A {
      ClassB* B;
    }
    

    クラスAはコードのある時点で破棄されます。クラスBも破棄されるのでしょうか、それともポインターとクラスBがメモリ内のどこかにまだ存在するのでしょうか?

31
ISTB

std :: vectorおよびstd :: strings:それらは自動的に破棄されますか?

はい(メンバー変数はstd::vectorおよびstd::stringへのポインターではないと仮定します)。

Std :: vectorのようなものがある場合、ベクトルデストラクタが呼び出されるとどうなりますか? myClassのデストラクタを自動的に呼び出しますか?または、ベクトルのみが破壊されますが、それに含まれるすべてのオブジェクトはまだメモリ内に存在しますか?

vector<MyClass>の場合、ベクターに含まれるすべてのオブジェクトが破棄されます。 vector<MyClass*>の場合、すべてのオブジェクトは明示的にdeletedである必要があります(破棄されるクラスがvector内のオブジェクトを所有していると仮定)。 3番目の選択肢は、vector<shared_ptr<MyClass>>のようなスマートポインターのvectorです。この場合、vectorの要素は明示的にdeletedである必要はありません。

クラス内に別のクラスへのポインターがある場合はどうなりますか

Bは、明示的にdeletedでなければなりません。繰り返しますが、スマートポインターを使用してBの破棄を処理できます。

38
hmjd

動的に作成したメモリについてのみ心配する必要があります(newでメモリを予約するとき)。

例えば:

Class Myclass{
   private:
       char* ptr;
   public:
       ~Myclass() {delete[] ptr;};
}
5
ElBaulP

場合によります。 std::vectorおよびstd::stringMyClassはすべて1つの共通点を持っています。変数をこれらの型のいずれかとして宣言すると、スタックに割り当てられ、現在のブロックに対してローカルになり、破壊されます。そのブロックが終了するとき。

例えば。

{
    std::vector<std::string> a;
    std::string b;
    MyClass c;
} //at this point, first c will be destroyed, then b, then all strings in a, then a.

ポインターを取得する場合、正しく推測しました:ポインター自体が占有するメモリ(通常は4バイト整数)のみがスコープを離れると自動的に解放されます。明示的にdeleteしない限り(ベクトル内にあるかどうかに関係なく)、指すメモリには何も起こりません。他のオブジェクトへのポインタを含むクラスがある場合、mayはデストラクタでそれらを削除する必要があります(そのクラスかどうかによって異なります)/ownsそれらのオブジェクト)。 C++ 11には、ポインターを「通常の」オブジェクトと同様の方法で処理できるポインタークラス(スマートポインターと呼ばれる)があることに注意してください。

例:

{
    std::unique_ptr<std::string> a = make_unique<std::string>("Hello World");
    function_that_wants_string_ptr(a.get());
} //here a will call delete on it's internal string ptr and then be destroyed
3
Cubic
  • 自動ストレージにある場合は、はい。あなたが持つことができます std::string* s = new std::string。この場合、自分で削除する必要があります。

  • 何も、あなたが所有するメモリを手動で削除する必要があります(newで割り当てられたメモリの場合)。

  • bnewを割り当てた場合、デストラクタで明示的に破棄する必要があります。

経験則として、delete/delete[]new/new[]コードに含まれています。

より良い経験則は、RAIIを使用し、生のポインターの代わりにスマートポインターを使用することです。

2
Luchian Grigore

std::vectorstd::stringおよび私が知る限り、他のすべてのSTLコンテナには自動デストラクタがあります。これは、メモリリークを防ぐため、newおよびdeleteの代わりにこれらのコンテナを使用した方がよい場合が多い理由です。

myClassオブジェクトへのポインターのベクトル(std::vector< myClass >ではなく、ベクトルがmyClassオブジェクトのベクトル(std::vector< myClass* >)である場合にのみ、myClassデストラクタが呼び出されます。 )。

最初の場合、std::vectorのデストラクタは、その各要素に対してmyClassのデストラクタも呼び出します。 2番目の場合、std::vectorのデストラクタはmyClass*のデストラクタを呼び出します。つまり、各ポインタを格納するために必要なスペースは解放されますが、myClassを格納するために必要なスペースは解放されませんオブジェクト自体。

指し示すClass Bオブジェクトは破棄されませんが、そのポインターを格納するために割り当てられたスペースは解放されます。

1
user1607425
  1. はい。 std::vectorstd::stringは、スコープから出ると自動的に含まれ、含まれるオブジェクトのデストラクタも呼び出します(std::vectorの場合)。

  2. 前に述べたように、std::vectorはスコープから外れると破棄され、含まれるオブジェクトのデストラクタを呼び出します。しかし実際、この場合、含まれるオブジェクトはポインターであり、ポインターが指すオブジェクトではありません。したがって、手動でdeleteする必要があります。

  3. (2)と同じ。 Aは破棄されるため、ポインターは破壊されますが、クラスBは指しません。 delete BというAのデストラクタを提供する必要があります。

C++ 11には非常に便利なソリューションがあります:std::unique_pointerを使用します。単一のオブジェクトを指す場合にのみ使用できます。これは、ポインターが範囲外になると削除されます(たとえば、std::vectorを破棄する場合)。

http://en.cppreference.com/w/cpp/memory/unique_ptr

1
user1434698

Std :: vectorのようなものがある場合、ベクトルデストラクタが呼び出されるとどうなりますか?

場合によります。

valuesstd::vector <MyClass>のベクトルがある場合、ベクトルのデストラクタは、ベクトル内のMyClassのすべてのインスタンスに対してデストラクタを呼び出します。

pointersstd::vector <MyClass*>のベクトルがある場合、MyClassのインスタンスを削除する必要があります。

クラス内に別のクラスへのポインターがある場合はどうなりますか

ClassBインスタンスはメモリに残ります。 ClassAデストラクタを使用してジョブを作成する可能な方法は、Bをインスタンスメンバまたはスマートポインタにすることです。

1
Andrey