2016-11-18 4 views
0

ベクトルを深く消去する方法は?C++ STLベクトルディープイレース

次のコードを検討してください。

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

using namespace std; 

int main(){ 
    vector<int> v {1,2,3,4,5}; 
    for_each(begin(v),end(v),[&v](int& n){ 
     static auto i = (int)0; 
     if(n == 2){ 
      v.erase (begin(v) +2, end(v)); 
     } 
     cout << n << " having index " << i++ << endl; 
    }); 
    v.erase (begin(v) +2, end(v)); 
    cout << v.size() << endl << v[4] << endl; 
} 

出力は私がしたいことは、私はエラーをスローするために無効とコンパイラであることを2から4にいずれかの[i]はVにアクセスしている

1 having index 0 
2 having index 1 
3 having index 2 
4 having index 3 
5 having index 4 
2 
4 

です。

簡単な言葉で言えば、ベクターを深く消去する方法は?

+2

これはUBです。あなたはそれを自分で確認する必要があります。代わりに 'std :: vector :: at'を使用してください。 – songyuanyao

+0

ベクトルはその要素を定義によって連続したメモリに格納するので、あなたが望むものはありません – user463035818

+1

そして、あなたはそれをコンパイル時のエラーにしたいと思っています。 – LogicStuff

答えて

1

未定義の動作を引き起こしているため、結果を信頼できません。あなたがあなた自身の施設や回避策をコーディングしない限り

あなたが境界をチェックする必要がある場合は、std::vector::at

vector<int> v{ 1,2,3,4,5 }; 
v.erase(begin(v) + 2, end(v)); 
try { 
    auto val = v.at(4); 
} catch (std::out_of_range&) { 
    cout << "out of range"; 
} 

を使用し、あなたはstd::vectorで、このようなコンパイル時のチェックをすることはできません。より多くの情報といくつかの提案はここにあります:https://stackoverflow.com/a/32660677/1938163

+0

演算子[]とメソッドのアクセスの違いは何ですか? – kalpa

+0

@calpa 'at'はバインドチェックを行い、範囲外の場合はランタイム例外をスローします –

+0

' [] 'を使ってベクトルにアクセスするのは悪い習慣ですか? – kalpa

1

私はすぐに例を挙げる時間がありませんが、これをきちんとやり遂げると思う唯一の方法は、カスタムクラスをラップまたはサブクラス化することです。特定のインデックスにエラーを投げるカスタムの[]at演算子を生成することができます。あなたは削除されたもののこのリストにindecesを追加する削除方法を持つことさえできます。

コンパイル時にエラーが必要な場合は、これがより難しくなります。 constexprアクセスオペレータとstatic_assertを使用して何かが可能かもしれないと思いますが、私は正確にどのように手を差し伸べているのか自信がありません。

+0

'operator []'がUBを生成し、範囲チェックをしない場合、なぜそれが許可されますか?また、 'at 'は' operator [] 'と比較してパフォーマンスオーバーヘッドを追加しますか?はいの場合、どれだけ重要ですか? – kalpa

+0

@kalpaあなたのコメントの2番目の文が最初に答える、[]があるのは遅いです、正確にどのくらい遅いかによって異なりますが、私は3〜10回実行すると思います。 – Vality

+0

'erase'メソッドまたは' clean'メソッドを呼び出すと、メモリが解放されるか、ベクトル全体が破棄されるまで割り当て解除されません。 – kalpa