最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++迭代器失效的情況匯總

 更新時間:2020年06月08日 09:29:10   作者:Boblim  
這篇文章主要介紹了C++迭代器失效的幾種情況總結(jié),文中代碼非常詳細,幫助大家更好的了解學(xué)習(xí),感興趣的朋友可以參考下

一、序列式容器(數(shù)組式容器)

對于序列式容器(如vector,deque),序列式容器就是數(shù)組式容器,刪除當(dāng)前的iterator會使后面所有元素的iterator都失效。這是因為vetor,deque使用了連續(xù)分配的內(nèi)存,刪除一個元素導(dǎo)致后面所有的元素會向前移動一個位置。所以不能使用erase(iter++)的方式,還好erase方法可以返回下一個有效的iterator。

for (iter = cont.begin(); iter != cont.end();)
{
  (*it)->doSomething();
  if (shouldDelete(*iter))
   iter = cont.erase(iter); //erase刪除元素,返回下一個迭代器
  else
   ++iter;
}

迭代器失效:

void vectorTest()
{
  vector<int> container;
  for (int i = 0; i < 10; i++)
  {
    container.push_back(i);
  }

  vector<int>::iterator iter;
   for (iter = container.begin(); iter != container.end(); iter++)
  {
      if (*iter > 3)
       container.erase(iter);
  }

   for (iter = container.begin(); iter != container.end(); iter++)
  {
      cout<<*iter<<endl;
  }
}

報錯是:vectoriterator not incrementable.

 迭代器在執(zhí)行++操作時報錯!已經(jīng)失效的迭代器不能再進行自增運算了。++代碼大致實現(xiàn)如下:

_Myiter operator++(int)
{
  _Myiter _Tmp=*this;
  ++*this;
  return (_Tmp);
}

對于序列式容器,比如vector,刪除當(dāng)前的iterator會使后面所有元素的iterator都失效。這是因為順序容器內(nèi)存是連續(xù)分配(分配一個數(shù)組作為內(nèi)存),刪除一個元素導(dǎo)致后面所有的元素會向前移動一個位置。(刪除了一個元素,該元素后面的所有元素都要挪位置,所以,iter++,已經(jīng)指向的是未知內(nèi)存)。

但是erase方法可以返回下一個有效的iterator。所以代碼做如下修改,就OK了。

void vectorTest()
{
  vector<int> container;
  for (int i = 0; i < 10; i++)
  {
    container.push_back(i);
  }

  vector<int>::iterator iter;
  for (iter = container.begin(); iter != container.end();)
  {
      if (*iter > 3) {
        iter = container.erase(iter);
      }
      else {
        iter ++;
      }

  }

  for (iter = container.begin(); iter != container.end(); iter++)
  {
      cout<<*iter<<endl;
  }
}

總結(jié):vector是一個順序容器,在內(nèi)存中是一塊連續(xù)的內(nèi)存,當(dāng)刪除一個元素后,內(nèi)存中的數(shù)據(jù)會發(fā)生移動,以保證數(shù)據(jù)的緊湊。所以刪除一個數(shù)據(jù)后,其他數(shù)據(jù)的地址發(fā)生了變化,之前獲取的迭代器根據(jù)原有的信息就訪問不到正確的數(shù)據(jù)。

所以為了防止vector迭代器失效,常用如下方法:

for (iter = container.begin(); iter != container.end(); )
{
      if (*iter > 3)
       iter = container.erase(iter);  //erase的返回值是刪除元素下一個元素的迭代器
      else{
        iter++;
      }
}

這樣刪除后iter指向的元素后,返回的是下一個元素的迭代器,這個迭代器是vector內(nèi)存調(diào)整過后新的有效的迭代器。

二、關(guān)聯(lián)式容器

對于關(guān)聯(lián)容器(如map, set,multimap,multiset),刪除當(dāng)前的iterator,僅僅會使當(dāng)前的iterator失效,只要在erase時,遞增當(dāng)前iterator即可。這是因為map之類的容器,使用了紅黑樹來實現(xiàn),插入、刪除一個結(jié)點不會對其他結(jié)點造成影響。erase迭代器只是被刪元素的迭代器失效,但是返回值為void,所以要采用erase(iter++)的方式刪除迭代器。

for (iter = cont.begin(); it != cont.end();)
{
  (*iter)->doSomething();
  if (shouldDelete(*iter))
   cont.erase(iter++);
  else
   ++iter;
}

//測試錯誤的Map刪除元素
void mapTest()
{
  map<int, string> dataMap;


  for (int i = 0; i < 100; i++)
  {
      string strValue = "Hello, World";

      stringstream ss;
      ss<<i;
      string tmpStrCount;
      ss>>tmpStrCount;
      strValue += tmpStrCount;
      dataMap.insert(make_pair(i, strValue));
  }

  cout<<"MAP元素內(nèi)容為:"<<endl;
   map<int, string>::iterator iter;
  for (iter = dataMap.begin(); iter != dataMap.end(); iter++)
  {
      int nKey = iter->first;
      string strValue = iter->second;
      cout<<strValue<<endl;
  }

  cout<<"內(nèi)容開始刪除:"<<endl;
  //刪除操作引發(fā)迭代器失效
  for (iter = dataMap.begin(); iter != dataMap.end();iter++)
  {
      int nKey = iter->first;
      string strValue = iter->second;

      if (nKey % 2 == 0)
      {
        dataMap.erase(iter);  //錯誤

      }
      /* cout<<iter->second<<endl;*/
  }
}

出錯:

解析:dataMap.erase(iter)之后,iter就已經(jīng)失效了,所以iter無法自增,即iter++就會出bug.解決方案,就是在iter失效之前,先自增。

void mapTest()
{
  map<int, string> dataMap;


  for (int i = 0; i < 100; i++)
  {
      string strValue = "Hello, World";

      stringstream ss;
      ss<<i;
      string tmpStrCount;
      ss>>tmpStrCount;
      strValue += tmpStrCount;
      dataMap.insert(make_pair(i, strValue));
  }

  cout<<"MAP元素內(nèi)容為:"<<endl;
  map<int, string>::iterator iter;
  for (iter = dataMap.begin(); iter != dataMap.end(); iter++)
  {
      int nKey = iter->first;
      string strValue = iter->second;
      cout<<strValue<<endl;
  }

  cout<<"內(nèi)容開始刪除:"<<endl;
  for (iter = dataMap.begin(); iter != dataMap.end();)
  {
      int nKey = iter->first;
      string strValue = iter->second;

      if (nKey % 2 == 0)
      {
        dataMap.erase(iter++);
        auto a = iter;

      }
      else {
        iter ++;
      }
  }
}

解析:dataMap.erase(iter++);這句話分三步走,先把iter傳值到erase里面,然后iter自增,然后執(zhí)行erase,所以iter在失效前已經(jīng)自增了。

map是關(guān)聯(lián)容器,以紅黑樹或者平衡二叉樹組織數(shù)據(jù),雖然刪除了一個元素,整棵樹也會調(diào)整,以符合紅黑樹或者二叉樹的規(guī)范,但是單個節(jié)點在內(nèi)存中的地址沒有變化,變化的是各節(jié)點之間的指向關(guān)系。

所以在map中為了防止迭代器失效,在有刪除操作時,常用如下方法:

for (iter = dataMap.begin(); iter != dataMap.end(); )
{
     int nKey = iter->first;
     string strValue = iter->second;

     if (nKey % 2 == 0)
     {
        map<int, string>::iterator tmpIter = iter;
      iter++;
        dataMap.erase(tmpIter);
        //dataMap.erase(iter++) 這樣也行

     }else
   {
     iter++;
     }
}

三、鏈表式容器

對于鏈表式容器(如list),刪除當(dāng)前的iterator,僅僅會使當(dāng)前的iterator失效,這是因為list之類的容器,使用了鏈表來實現(xiàn),插入、刪除一個結(jié)點不會對其他結(jié)點造成影響。只要在erase時,遞增當(dāng)前iterator即可,并且erase方法可以返回下一個有效的iterator。

方式一:遞增當(dāng)前iterator

for (iter = cont.begin(); it != cont.end();)
{
  (*iter)->doSomething();
  if (shouldDelete(*iter))
   cont.erase(iter++);
  else
   ++iter;
}

方式二:通過erase獲得下一個有效的iterator

for (iter = cont.begin(); iter != cont.end();)
{
  (*it)->doSomething();
  if (shouldDelete(*iter))
   iter = cont.erase(iter); //erase刪除元素,返回下一個迭代器
  else
   ++iter;
}

四、總結(jié)

迭代器失效分三種情況考慮,也是分三種數(shù)據(jù)結(jié)構(gòu)考慮,分別為數(shù)組型,鏈表型,樹型數(shù)據(jù)結(jié)構(gòu)。

數(shù)組型數(shù)據(jù)結(jié)構(gòu):該數(shù)據(jù)結(jié)構(gòu)的元素是分配在連續(xù)的內(nèi)存中,insert和erase操作,都會使得刪除點和插入點之后的元素挪位置,所以,插入點和刪除掉之后的迭代器全部失效,也就是說insert(*iter)(或erase(*iter)),然后在iter++,是沒有意義的。解決方法:erase(*iter)的返回值是下一個有效迭代器的值。 iter =cont.erase(iter);

鏈表型數(shù)據(jù)結(jié)構(gòu):對于list型的數(shù)據(jù)結(jié)構(gòu),使用了不連續(xù)分配的內(nèi)存,刪除運算使指向刪除位置的迭代器失效,但是不會失效其他迭代器.解決辦法兩種,erase(*iter)會返回下一個有效迭代器的值,或者erase(iter++).

樹形數(shù)據(jù)結(jié)構(gòu): 使用紅黑樹來存儲數(shù)據(jù),插入不會使得任何迭代器失效;刪除運算使指向刪除位置的迭代器失效,但是不會失效其他迭代器.erase迭代器只是被刪元素的迭代器失效,但是返回值為void,所以要采用erase(iter++)的方式刪除迭代器。

注意:經(jīng)過erase(iter)之后的迭代器完全失效,該迭代器iter不能參與任何運算,包括iter++,*ite

以上就是c++迭代器失效的情況匯總的詳細內(nèi)容,更多關(guān)于c++迭代器失效的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++中指針和引用的區(qū)別詳解

    C++中指針和引用的區(qū)別詳解

    這篇文章主要介紹了C++中指針和引用的區(qū)別詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 在QT中將QString轉(zhuǎn)換為char*類型的完整方案

    在QT中將QString轉(zhuǎn)換為char*類型的完整方案

    本文詳細介紹了在Qt中將QString轉(zhuǎn)換為char*的完整方案和注意事項,核心方法是通過QByteArray中轉(zhuǎn),推薦使用toUtf8()編碼以支持中文,并強調(diào)必須分步操作避免臨時對象銷毀導(dǎo)致的指針懸空問題,文章對比了UTF-8、Latin1等不同編碼的適用場景,提供了處理中文亂碼的解決方案
    2026-01-01
  • C++多態(tài)詳解之從靜態(tài)多態(tài)到動態(tài)多態(tài)

    C++多態(tài)詳解之從靜態(tài)多態(tài)到動態(tài)多態(tài)

    C++多態(tài)技術(shù)是面向?qū)ο缶幊痰闹匾匦?這篇文章主要介紹了C++多態(tài)詳解之從靜態(tài)多態(tài)到動態(tài)多態(tài)的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-12-12
  • C++運算符重載圖文詳解

    C++運算符重載圖文詳解

    運算符重載的方法是定義一個重載運算符的函數(shù),在需要執(zhí)行被重載的運算符時,系統(tǒng)就自動調(diào)用該函數(shù),以實現(xiàn)相應(yīng)的運算。也就是說,運算符重載是通過定義函數(shù)實現(xiàn)的
    2021-09-09
  • c語言B樹深入理解

    c語言B樹深入理解

    B樹是為磁盤或其他直接存儲設(shè)備設(shè)計的一種平衡查找樹,本文將詳細介紹c語言B樹,需要的朋友可以參考下
    2012-11-11
  • c語言求1+2+...+n的解決方法

    c語言求1+2+...+n的解決方法

    本篇文章是對在c語言中求1+2+...+n的解決方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++實現(xiàn)String類的方法詳解

    C++實現(xiàn)String類的方法詳解

    在C語言中,沒有專門用來表示字符串的類型。雖然C語言為字符串提供了一系列的庫函數(shù),但這些函數(shù)與字符串這個類型是分開的。所以在C++中封裝了一個string類,來幫助我們操作字符串,本文就為大家提供了實現(xiàn)String類的方法,需要的可以參考一下
    2022-08-08
  • C語言實現(xiàn)學(xué)生學(xué)籍管理系統(tǒng)課程設(shè)計

    C語言實現(xiàn)學(xué)生學(xué)籍管理系統(tǒng)課程設(shè)計

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)學(xué)生學(xué)籍管理系統(tǒng)課程設(shè)計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • c++11 多線程編程——如何實現(xiàn)線程安全隊列

    c++11 多線程編程——如何實現(xiàn)線程安全隊列

    這篇文章主要介紹了c++ 如何實現(xiàn)線程安全隊列,幫助大家更好的理解和學(xué)習(xí)c++的相關(guān)知識,感興趣的朋友可以了解下
    2020-11-11
  • C語言中全局?jǐn)?shù)組和局部數(shù)組的問題

    C語言中全局?jǐn)?shù)組和局部數(shù)組的問題

    今天同學(xué)遇到一個在C語言中全局?jǐn)?shù)組和局部數(shù)組的問題,卡了許久,我也沒有第一時間看出問題,現(xiàn)在把問題梳理一下,并給出解決方案,需要的朋友可以參考下
    2012-12-12

最新評論

连云港市| 扶沟县| 潮州市| 包头市| 重庆市| 化隆| 裕民县| 淮安市| 涿鹿县| 锦屏县| 汉源县| 阜康市| 金门县| 彭州市| 越西县| 葫芦岛市| 育儿| 陵川县| 广安市| 宁强县| 资溪县| 日土县| 建平县| 铁岭市| 开平市| 牡丹江市| 平阴县| 微山县| 卢龙县| 巩留县| 鲜城| 西藏| 洛川县| 望奎县| 鹰潭市| 左云县| 玛多县| 安岳县| 屏南县| 南郑县| 云霄县|