2016-10-28 4 views
1

リストを変更してリストが空であれば、std :: listの逆過去エンドイテレータは無効になります。しかし、言語仕様リストによると、push_backはイテレータには影響しません。std list逆反復子の過去イテレータは、リストが空の場合に無効化されます。

コンテナの最後に指定された要素の値を追加します。 1)新しい要素は、値のコピーとして初期化されます。 2)値が新しい要素に移動されます。 イテレータまたは参照は無効になりません。

これは私がlanguage specに気付いたとおりです。下のリストの例では、別の方法で動作を見つけることができます。

//Add or replace an element using reverse iterator 
void addOrReplaceRev(std::list<int>& list, int val) 
{ 
    auto rit = std::find(list.rbegin(), list.rend(), val); 
    list.push_back(val); //invalidates the rend() iterator, if list empty 
    if(rit != list.rend()) //remove if the value existed earlier 
     list.erase((++rit).base()); 

} 

void addOrReplace(std::list<int>& list, int val) 
{ 
    auto rit = std::find(list.rbegin(), list.rend(), val); 
    bool shouldErase = rit != list.rend(); //save the result before modification 
    list.push_back(val); 
    if(shouldErase) //All good, as we use saved query result 
     list.erase((++rit).base()); 
} 

int main() 
{ 
    std::list<int> mylist1; 
    std::list<int> mylist2 = {1,2,4,5}; 

    addOrReplaceRev(mylist1, 3); //empty list messes up with rev iters 
    addOrReplaceRev(mylist2, 3); //non-empty lists are fine 
    printf("SIZES %d:%d\n", mylist1.size(), mylist2.size()); 

    std::list<int> mylist3; 
    std::list<int> mylist4 = {1,2,4,5}; 

    addOrReplace(mylist3, 3);//if results are saved 
    addOrReplace(mylist4, 3); 
    printf("SIZES %d:%d\n", mylist3.size(), mylist4.size()); 
} 

プログラムの出力は

SIZES 0:5 
SIZES 1:5 

。注:私は前方/定期的なイテレータを使用する場合、私は、この動作は表示されません。私はgcc 4.9.2コンパイラを使用しています。これは期待されているのか、コンパイラのバグですか?

`

+0

名前に「イテレータ」があるにもかかわらず、コンテナのイテレータに適用される保証が必ずしもその逆イテレータに当てはまるとは限りません。 – user2357112

答えて

0

リバースイテレータは直接、コンテナのイテレータではないではありません。それらはコンテナのイテレータの観点から定義されています。

一般に、逆方向反復子には、基本的な "通常の"反復子があります。逆イテレータが参照する要素は基本要素が参照する要素ではなく、要素の前にあり、の前には基本イテレータの要素です。

rendreverse(begin)である(1-前-始める何イテレータが存在しないためです)。空のリストには、begin==end。したがってrendreverse(end)です。

リストに挿入すると、イテレータは無効になりません。 rendのコピーはreverse(end)のままですが、rendを再度呼び出すとreverse(begin)が返されます。そして彼らはもはや平等ではありません。

私にとって、これは驚くようですが、それは準拠していると思います。 C++標準では、この「バグ」を合理的に回避することはできませんでした。

+0

'@ Yakk'ありがとう。私は空リストのために、 'begin'と' end'が等しいという部分を見逃しました。それにもかかわらず、あなたが言ったように、私はこの動作に驚いています。特に、空で空でないリストに対して2つの異なる動作が得られるということです。 –

関連する問題