国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

[C++] STL_vector 迭代器失效問題

這篇具有很好參考價值的文章主要介紹了[C++] STL_vector 迭代器失效問題。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

1、前言

**迭代器的主要作用就是讓算法能夠不用關(guān)心底層數(shù)據(jù)結(jié)構(gòu),其底層實際就是一個指針,或者是對指針進行了封裝,比如:string的迭代器就是原生指針char,vector的迭代器就是原生態(tài)指針T因此迭代器失效,實際就是迭代器底層對應(yīng)指針所指向的空間被銷毀了,而使用一塊已經(jīng)被釋放的空間,造成的后果是程序崩潰(即如果繼續(xù)使用已經(jīng)失效的迭代器,程序可能會崩潰)。
對迭代器失效我們了解了,那么現(xiàn)在我們就分析,在vector中哪些操作會導致迭代器失效。

2、情況一:底層空間改變的操作

存在底層空間改變的函數(shù)接口有:resize、reserve、insert、assign、push_back等。
產(chǎn)生的原因:
這幾個接口都存在擴容的問題,擴容的時候存在異地擴容,當異地擴容后,原本的空間被釋放,但是迭代器指的是被釋放空間,這就會導致迭代器的失效問題,會引發(fā)程序崩潰的問題。
解決方法:
一旦存在擴容,擴容后對迭代器更新一次,重新給迭代器賦值即可。
舉例:
我們看一下insert接口。
[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

我們由圖中可以看到,當我們需要在3之前插入數(shù)據(jù)30,但是空間已經(jīng)滿了,因此我們需要進行擴容,擴容是異地開空間,開好空間將舊空間的數(shù)據(jù)拷貝回來,并將舊空間釋放掉,_start指向新的空間頭部,但是it指的是舊空間的位置,這就是迭代器失效。我們記住it相對于_start的相對位置,在新空間開好后,更新it,讓其指向新空間的相對位置。(方式:計算出it到_start的距離len,開好新空間后,更新it為新的_start+len)。
代碼實現(xiàn):

iterator insert(iterator pos, const T& x)
{
    assert(pos >= _start);
    assert(pos <= _finish);

    if (_finish == _endOfStorage)
    {
        size_t len = pos - _start;//先記下_start到pos位置的距離,因為擴容后迭代器pos就會失效
        reserve(capacity() == 0 ? 4 : 2 * capacity());
        pos = _start + len;//新的空間需要更新迭代器pos
    }

    iterator end = _finish - 1;
    //挪動數(shù)據(jù)
    while (end >= pos)
    {
        *(end + 1) = *end;
        --end;
    }

    *pos = x;
    ++_finish;

    return pos;
}

3、情況二:指定位置元素的刪除操作

對于erase接口也會導致迭代器失效問題。那它是怎么導致的呢,我們來分析一下。
產(chǎn)生原因:
在erase刪除pos位置元素后,pos位置之后的元素會往前搬移,沒有導致底層空間的改變,理論上講迭代器不應(yīng)該會失效,但是:如果pos剛好是最后一個元素,刪完之后pos剛好是end的位置,而end位置是沒有元素的,那么pos就失效了。因此刪除vector中任意位置上元素時,vs就認為該位置迭代器失效了。
[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

#include <iostream>
using namespace std;
#include <vector>

int main()
{
    int a[] = { 1, 2, 3, 4 };
    vector<int> v(a, a + sizeof(a) / sizeof(int));
    // 使用find查找3所在位置的iterator
    vector<int>::iterator pos = find(v.begin(), v.end(), 3);
    // 刪除pos位置的數(shù)據(jù),導致pos迭代器失效。
    v.erase(pos);
    cout << *pos << endl; // 此處會導致非法訪問
    return 0;
}

解決方法:
本質(zhì)是因為尾刪導致的迭代器失效問題,因此我們在尾刪完后,返回it的下一個位置,我們的模擬實現(xiàn)是數(shù)據(jù)覆蓋(it+1覆蓋it),因此返回的還是it,一刪之后 --_finish,當 it指的位置就是_finish 的時候正好也就停止了,因此也就解決了迭代器失效的問題。
代碼實現(xiàn):

iterator erase(iterator pos)
{
    assert(pos >= _start);
    assert(pos < _finish);

    iterator it = pos + 1;
    //挪動數(shù)據(jù)
    while (it < _endOfStorage)
    {
        *(it - 1) = *it;
        ++it;
    }
    --_finish;

    return pos;
}

4、g++編譯器對迭代器失效檢測

Linux下,g++編譯器對迭代器失效的檢測并不是非常嚴格,處理也沒有vs2019下極端。
我們來看下面這幾種情況下,代碼在vs2019和g++下不同的表現(xiàn)。

4.1 擴容

int main()
{
    vector<int> v{1,2,3,4,5};
    for(size_t i = 0; i < v.size(); ++i)
    	cout << v[i] << " ";
    cout << endl;
    
    auto it = v.begin();
    cout << "擴容之前,vector的容量為: " << v.capacity() << endl;

    v.reserve(100);
    cout << "擴容之后,vector的容量為: " << v.capacity() << endl;
    
    while(it != v.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    
    return 0;
}

g++下運行結(jié)果:
[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

vs2019下運行結(jié)果:
[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

vs2019下程序崩潰了。
結(jié)論:當擴容后迭代器就是失效的,g++下雖然能運行,但是結(jié)果出錯了,vs下直接程序崩潰。

4.2 erase刪除任意位置(非尾刪)

#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    vector<int> v{1,2,3,4,5};
    vector<int>::iterator it = find(v.begin(), v.end(), 3);
    
    v.erase(it);
    cout << *it << endl;
    
    while(it != v.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    
    return 0;
}

g++下運行結(jié)果:
[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

vs2019下運行結(jié)果:
[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

結(jié)論:在非尾刪的刪除中,空間是沒有變的,迭代器指的是還是那塊空間,g++下迭代器沒有失效,刪除后后面的數(shù)據(jù)前移,it位置沒失效,vs下只要是erase,就判斷為迭代器失效了。

4.3 erase尾刪

int main()
{
	vector<int> v{1,2,3,4,5,6};

	auto it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
			v.erase(it);
		++it;
	}

	for (auto e : v)
		cout << e << " ";
	cout << endl;

	return 0;
}

g++下運行結(jié)果:
[C++] STL_vector 迭代器失效問題,C++,c++,java,數(shù)據(jù)庫

vs2019下不用看,直接崩潰。
結(jié)論:當在尾刪的時候,刪除之后存在數(shù)據(jù)挪動,一挪動_finish與it是一個位置了,erase本就返回被刪除位置的下一個位置,此時迭代器失效,再++it程序直接崩潰。

5、總結(jié)

本篇主要講了擴容、插入、刪除造成的迭代器失效,g++對迭代器失效檢測的不嚴格,而vs對迭代器失效檢測很嚴格,直接崩潰。
1、擴容一般都要更新迭代器,我們不知道哪一次的擴容是異地擴。
2、插入任意位置時,一旦存在擴容就要更新迭代器,本質(zhì)就是擴容要更新迭代器。
3、刪除任意位置時,g++下非尾刪不考慮迭代器失效問題,尾刪一定要注意迭代器失效問題;vs2019中刪除就認定為迭代器失效,直接崩潰。文章來源地址http://www.zghlxwxcb.cn/news/detail-675234.html

到了這里,關(guān)于[C++] STL_vector 迭代器失效問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • [STL-list]介紹、與vector的對比、模擬實現(xiàn)的迭代器問題

    [STL-list]介紹、與vector的對比、模擬實現(xiàn)的迭代器問題

    ?list的底層是 帶頭雙向鏈表 結(jié)構(gòu),雙向鏈表中每個元素存儲在互不相關(guān)的獨立節(jié)點中,在節(jié)點中通過指針指向其前一個元素和后一個元素。 與其他的序列式容器相比(array,vector,deque),list通常 在任意位置進行插入、移除元素的執(zhí)行效率更好 list最大的缺陷是 不支持任意位

    2024年04月15日
    瀏覽(23)
  • 【C++庖丁解?!縎TL之vector容器的介紹及使用 | vector迭代器的使用 | vector空間增長問題

    【C++庖丁解?!縎TL之vector容器的介紹及使用 | vector迭代器的使用 | vector空間增長問題

    ??你好,我是 RO-BERRY ?? 致力于C、C++、數(shù)據(jù)結(jié)構(gòu)、TCP/IP、數(shù)據(jù)庫等等一系列知識 ??感謝你的陪伴與支持 ,故事既有了開頭,就要畫上一個完美的句號,讓我們一起加油 vector的文檔介紹 vector是表示可變大小數(shù)組的序列容器。 就像數(shù)組一樣,vector也采用的連續(xù)存儲空間來存

    2024年03月14日
    瀏覽(36)
  • 【C++】vector模擬實現(xiàn)+迭代器失效

    【C++】vector模擬實現(xiàn)+迭代器失效

    鐵汁們,今天給大家分享一篇vector模擬實現(xiàn) + 迭代器失效,來吧,開造?? 指向最后一個空間的下一個位置 ?? iterator _endofstorage 指向存儲第一個有效數(shù)據(jù)空間的位置 ?? iterator _start 指向存儲最后一個有效數(shù)據(jù)空間的下一個位置 ?? iterator _finish 在成員變量聲明處給缺省值,

    2024年02月21日
    瀏覽(86)
  • STL之list模擬實現(xiàn)(反向迭代器講解以及迭代器失效)

    這次是關(guān)于list的模擬實現(xiàn)的代碼,先看看下面的代碼: 上面是list的代碼,其底層是一個帶頭雙向循環(huán)的鏈表,實現(xiàn)的方法就不說了,相信大家已經(jīng)都會了,然后自己實心的list我沒有寫析構(gòu)函數(shù)等,這個也很簡單,循環(huán)利用成員函數(shù)中的刪除函數(shù)就可以。 先來說說個人認為

    2024年02月11日
    瀏覽(19)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】C++的STL模板(迭代器iterator、容器vector、隊列queue、集合set、映射map)以及算法例題

    【數(shù)據(jù)結(jié)構(gòu)與算法】C++的STL模板(迭代器iterator、容器vector、隊列queue、集合set、映射map)以及算法例題

    更多算法例題鏈接: 【數(shù)據(jù)結(jié)構(gòu)與算法】遞推法和遞歸法解題(遞歸遞推算法典型例題) 什么是迭代器(iterator) 迭代器(iterator)的定義: 迭代器是一種檢查容器內(nèi)元素并遍歷元素的數(shù)據(jù)類型。 迭代器提供對一個容器中的對象的訪問方法,并且定義了容器中對象的范圍。 容器

    2024年04月14日
    瀏覽(30)
  • STL常用梳理——VECTOR常用接口及其迭代器實現(xiàn)

    STL常用梳理——VECTOR常用接口及其迭代器實現(xiàn)

    vector是STL中容器之一,特性如下: vector是表示可變大小數(shù)組的序列容器。 就像數(shù)組一樣,vector也采用的連續(xù)存儲空間來存儲元素。也就是意味著可以采用下標對vector的元素 進行訪問,和數(shù)組一樣高效。但是又不像數(shù)組,它的大小是可以動態(tài)改變的,而且它的大小會被容器自

    2024年02月05日
    瀏覽(29)
  • STL標準模板庫 vector容器與迭代器入門

    STL標準模板庫 vector容器與迭代器入門

    vector 就是一個連續(xù)的數(shù)據(jù) C++11 std::vector a ={1,4,2,6,7}; 可以使用花括號來定義 容器的功能就是存儲數(shù)據(jù) 迭代器的功能就是指向數(shù)據(jù),并且可以實現(xiàn)前后移動(指針)算法和容器的接口的存在 vector功能是長度可變的數(shù)組, 身在棧上 里面的數(shù)據(jù)存儲在堆上 因為棧不可動態(tài)擴容

    2023年04月23日
    瀏覽(32)
  • 【c++】list迭代器失效問題

    【c++】list迭代器失效問題

    目錄 一、list iterator的使用 二、list的迭代器失效 ? ? ? ? 對于list的迭代器的用法,可以將它看做一個指針(實際要更加復雜)來使用,該指針指向list中的一個節(jié)點。 ? ? ? ? 【注意】 ? ? ? ? (1)begin和end為正向迭代器,對迭代器執(zhí)行++操作,迭代器向后移動 ? ? ? ? (2)r

    2024年01月23日
    瀏覽(23)
  • C++筆記之迭代器失效問題處理

    C++筆記之迭代器失效問題處理

    code review! 參考博文:C++STL迭代器失效的幾種情況總結(jié) 對于 std::vector 來說,擦除(erase)元素會導致迭代器失效。具體而言

    2024年02月14日
    瀏覽(15)
  • JPA連接達夢數(shù)據(jù)庫導致auto-ddl失效問題解決

    JPA連接達夢數(shù)據(jù)庫導致auto-ddl失效問題解決

    ? 現(xiàn)象: ? ? ? ? 項目使用了JPA,并且auto-ddl設(shè)置的為update,在連接達夢數(shù)據(jù)庫的時候,第一次啟動沒有問題,但是后面重啟就會報錯,發(fā)現(xiàn)錯誤為重復建表,也就是說已經(jīng)建好的表沒有檢測到,又重新走的建表流程。經(jīng)過一天的排查,總結(jié)了2個解決方案。 ?問題的根源:

    2024年02月15日
    瀏覽(123)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包