2016-04-12 5 views
-5

これは、編集されたコードイテレータをコピーせずにメモリリークを起こさずにSTLベクタの要素を消去する方法は?

vector<vector<int> > vec; 
vector<vector<int> >::iterator vit; 
vector<int>::iterator it; 
for (vit = vec.begin(); vit != vec.end(); ++vit) 
{ 
    it = vit->begin(); 
    while(it != vit->end()) 
    { 
     while(it != vit->end()) 
     { 

      if(condition) 
      { 
       while(condition) 
       { 
        //going back to certain it 
        //erase an element 
        it = vit->erase(it); 
       } 
      } 
      else 
       ++it; 
     } 
     ++it; 
    } 
} 

内側ながらバックある点にループです。リンクがありません。 イテレータをコピーせずに、バックループでメモリリークのない要素を消去し、再度転送しますか?

+1

'ながら(これ< vit->端()) ' - これはすでにバグあります。 – IInspectable

+2

[ループしている間に要素をベクターから削除するにはどうすればいいですか?](http://stackoverflow.com/questions/8597240/how-to-delete-an-element-from-a-vector-while- looping-over-it) – Pixelchemist

答えて

0

に削除するためにvector.remove(*it)を使用しています。そのような場合にSTLコンテナを使用すると、リークアルゴリズムを使用した後にベクトルを縮小しないと「リーク」することがあります。

以下はあなたのコードを修正したものであり、書き換え全体ではありません。

vector<vector<int> > vec = { {0,1,2,3}, {0,1,2,3,4,5}, {0,1} }; 
vector<vector<int> >::iterator vit = vec.begin(); 
vector<int>::iterator it; 

while(vit != vec.end()) { 
    it = vit->begin(); 
    while(it != vit->end()) { 
    if(*it == 1) { 
     it = vit->erase(it); 

     // Not sure why you want this loop here 
     //while(condition) 
     //{ 
     //  **erase an element;** 
     //} 
    } 
    else { 
     ++it; 
    } 
    } 
    ++vit; 
} 

for (auto it1 = vec.begin(); it1 != vec.end(); ++it1){ 
    for (auto it2 = it1->begin(); it2 != it1->end(); ++it2) 
     std::cout<<*it2<< ", "; 
    std::cout << "\n"; 
} 

が生成する:このコードは、1 [LIVE]に等しいすべての値を削除し

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out 
0, 2, 3, 
0, 2, 3, 4, 5, 
0, 
+0

ありがとう。内部の 'while'ループは特定のポイントに戻りますが、戻ってくる要素はある条件で消去されます。逆方向および前進、リンクの不足に問題があります。 –

+0

@RaghuG私はおそらく分かりませんが、動作するベクトルの範囲内であれば、新しいiteratorに 'it'を再割り当てすることができます。私の例では、 'it'を' vit-> begin() 'に代入してから、あなたの内側のループでもう一度iterateするか、別のイテレータを使うことをお勧めします。 – marcinj

+0

MarcinJędrzejewskiありがとうございました。新しいイテレータを割り当てることによって問題を解決しました。 –

3

この目的でerase-remove idiomを使用できます。あなたはこのようにラムダを使用して同じことを達成することができます。もちろん、

#include <iostream> 
#include <vector> 
#include <algorithm> 

bool is_odd(const int &i) 
{ 
    return (i % 2) != 0; 
} 

int main() 
{ 
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
    // removes all odd numbers 
    v.erase(std::remove_if(v.begin(), v.end(), is_odd), v.end()); 
    for(const auto &i:v) 
    { 
     std::cout << i << ' '; 
    } 
    return 0; 
} 

簡単な例あなたは、内側のベクトルの特定の要素を削除したい場合は

#include <iostream> 
#include <vector> 
#include <algorithm> 

int main() 
{ 
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
    // removes all odd numbers 
    v.erase(std::remove_if(v.begin(), v.end(), 
     [](const int &i) -> bool {return (i % 2) != 0;}), 
     v.end()); 
    for(const auto &i:v) 
    { 
     std::cout << i << ' '; 
    } 
    return 0; 
} 
+1

イディオムが何であるかをコードスニペットに含めるとよいでしょう。 – Niall

+0

@ Niallと完全に同意します。リンクはある時点で中断する傾向があります – user463035818

+0

あなたは絶対に正しいです@ニオール。簡単な例を追加しました。 :) – Mayhem

6

は上erase-remove idiomを使用しますそれら:

for (auto & intv : vec) 
{ 
    intv.erase( 
    std::remove_if(intv.begin(), intv.end(), 
     [](int value) -> bool { return value == 2; }), 
    intv.end()); 
} 

注:

  1. vecまたは他のローカル変数に応じて、ラムダ式でキャプチャすることで特定の条件を適用できます。

  2. この例では、2に等しい内側のベクトルからすべての要素を削除します。

  3. intの場合、ラムダパラメータを値渡すことが好ましい。より大きなオブジェクトの場合は、おそらくconst参照ラムダパラメータを持つことが必要です。

1

STLベクタの消去機能を使用できます。ただ、あなたがのstd ::何のメモリがリークされていないことを確認するRAIIを使用して、ベクターを使用し、あなたの場合には、メモリリークを心配する必要はいけない要素

関連する問題