web-dev-qa-db-ja.com

関数の最後で常にベクトルclear()を呼び出す必要がありますか?

私はこのようなベクトルを使用するいくつかの単純な関数を持っています(擬似コード):

void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    // should I call the clear() here or this could be ommited ?
    contentVector.clear();

}

Clear()を呼び出す必要がありますか、それとも省略できますか?

29

cppreference.com エントリ std :: vector :: 〜vector を見ると、次のようになっています。

コンテナを破壊します。要素のデストラクタが呼び出され、使用されているストレージの割り当てが解除されます。要素がポインタの場合、ポイントされたオブジェクトは破棄されないことに注意してください。

したがって、 clear を呼び出す必要はありません。

ドラフト標準 に移動する場合は、セクション23.2.1一般的なコンテナ要件段落を確認する必要があります。 4これは次のように述べています:

表96および97で、XはタイプTのオブジェクトを含むコンテナクラスを示し、aおよびbはタイプXの値を示します。[...]

次に、次の式エントリを持つTable 96 — Container requirementsを確認します。

(&a)->~X()  

および次の注:

注:デストラクタはaのすべての要素に適用されます。すべてのメモリの割り当てが解除されます。

更新

これは [〜#〜] raii [〜#〜] 動作中であり、Bjarne StroustrupC++が「最終的に」構成を提供しないのはなぜですか?

C++は、ほとんどの場合、より優れた代替手段をサポートしているため、「リソースの取得は初期化です」という手法(TC++ PL3セクション14.4)です。基本的な考え方は、ローカルオブジェクトによってリソースを表すことです。これにより、ローカルオブジェクトのデストラクタがリソースを解放します。そうすれば、プログラマーはリソースを解放することを忘れることはできません。

28
Shafik Yaghmour

それをする必要は全くありません。 _std::vector_および他のすべてのコンテナーは、それら自体が破棄されるときに、それらの要素を自動的に破棄します。つまり、デストラクタがそのアクションに責任があるということです。だから、しないでください。

これの美しさは、コンテナが当然例外安全であるということです[1]

_void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    throw std::runtime_error("I just want to throw!");

    contentVector.clear();
}
_

contentVector.clear();が呼び出されますか?いいえ。ただし、contentVectorのデストラクタが呼び出されることが保証されているため、安全です。

から ベクトル[2]

コンテナを破壊します。要素のデストラクタが呼び出され、使用されているストレージの割り当てが解除されます。要素がポインタの場合、ポイントされたオブジェクトは破棄されないことに注意してください。


[1]ただし、要素を例外安全にする必要があります(デストラクタが呼び出されるたびに、要素がリソースを適切に解放するようにします)。

[2]SGI STLドキュメントに関するいくつかの考えについては、以下のコメントを参照してください。

15
Mark Garcia

必要ありません。スコープ外になると自動的にクリアされます。つまり、 デストラクタはコンテナオブジェクトを破棄します。

5
Varo

vectorのデストラクタ はcontentVectorが '}'でスコープ外になると実行されるため、.clear()関数の使用を省略できます。

これにより、ベクターのデータを格納するメモリの割り当てが解除されます。

1
DaBuj

私は他の誰もこれに言及していないと思うので、しかしあなたのベクトルが

std::vector<std::string*> vector;

関数が終了する前に、各要素に割り当てられたメモリを解放する必要があります(グローバル変数など、他の場所に所有権を譲渡した場合を除く)

for (auto i : vector) {
  delete i;
}
1
Michael