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

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析

這篇具有很好參考價(jià)值的文章主要介紹了【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

??博主CSDN主頁(yè):杭電碼農(nóng)-NEO??
?
?專欄分類:C++從入門到精通?
?
??代碼倉(cāng)庫(kù):NEO的學(xué)習(xí)日記??
?
??關(guān)注我??帶你學(xué)習(xí)C++
? ????


【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言

1. 前言

在閱讀本篇文章前,一定要先看前集:

vector深度剖析(上)

本章重點(diǎn):

本章會(huì)重點(diǎn)講解vector迭代器失效問(wèn)題
以及vector中的深淺拷貝問(wèn)題
并且簡(jiǎn)單完善一下vector的自我實(shí)現(xiàn)

在此之前,我將在文章末尾把vector
自我實(shí)現(xiàn)的完整代碼分享給大家


2. 什么是迭代器失效?

首先我們要清楚一點(diǎn):
vector的每一次擴(kuò)容都不是在
原地?cái)U(kuò)容,而是新開(kāi)辟一塊兒空間后
將原先的數(shù)據(jù)拷貝到新空間

請(qǐng)看下面的代碼:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
auto pos = find(v.begin(),v.end(),3);
v.insert(pos,30);
v.insert(pos,40);

這段代碼在3前面插入一個(gè)30和40
但是這段代碼會(huì)出錯(cuò)!

為什么呢?請(qǐng)看下圖:

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言

注:從四個(gè)數(shù)據(jù)插入為五個(gè)會(huì)擴(kuò)容

  • 擴(kuò)容前
    迭代器pos在start和finish之間
  • 擴(kuò)容后
    start和finish的地址改變,pos失效
    pos不再指向現(xiàn)在的位置3

迭代器失效的本質(zhì)原因是:
擴(kuò)容后start和finish的地址發(fā)生變化
指向原先位置的迭代器統(tǒng)統(tǒng)失效!

若沒(méi)發(fā)生擴(kuò)容,則一切安好!


3. 迭代器失效的經(jīng)典案例

除了前面講到的insert導(dǎo)致迭代器失效外
erase函數(shù)也會(huì)導(dǎo)致迭代器失效

請(qǐng)看下面的案例:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(4);
v.push_back(6);

for (auto e : v)
{
	cout << e << " ";
}
cout << endl;
auto it = v.begin();
while (it != v.end())
{
	if (*it % 2 == 0)
	{
		it = v.erase(it);
	}
	++it;
}

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

這段代碼在刪除順序表中所有的偶數(shù)
但是你會(huì)發(fā)現(xiàn)它并沒(méi)有刪除完
這是為啥呢?請(qǐng)看下圖的分析

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言

erase刪除后,后面的數(shù)據(jù)會(huì)覆蓋過(guò)來(lái)
此時(shí)不讓迭代器++它也指向下一個(gè)位置

注:在VS編譯器中.只要使用了erase函數(shù)
編譯器自動(dòng)認(rèn)為此位置迭代器失效
所以在VS上進(jìn)行多次erase操作時(shí)
一定要不斷更新迭代器的位置!


4. 迭代器失效的解決方案

  1. 對(duì)于insert來(lái)說(shuō)

在pos位置使用一次insert后
不要再次直接訪問(wèn)pos迭代器
一定要更新了pos之后再去訪問(wèn)!

庫(kù)中的vector提供了返回值來(lái)解決此問(wèn)題:

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言

insert會(huì)返回一個(gè)迭代器,此迭代器的
返回的是新插入元素的迭代器

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言

請(qǐng)看下圖理解:

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言
所以以后我們可以這樣寫代碼:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
vector<int>::iterator it = v.begin();
while(it!=v.end())
{
	it = insert(it,100);
	it+=2;
}
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;

在每一個(gè)元素前插入一個(gè)100

  1. 對(duì)于erase來(lái)說(shuō)

刪除后不用再++迭代器
只用在沒(méi)刪除的時(shí)候再++

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(4);
v.push_back(5);
v.push_back(6);
auto it = v.begin();
while (it != v.end())
{
	if (*it % 2 == 0)
	{
		it = v.erase(it);
	}
	else
	{
		++it;
	}
}
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;


5. 對(duì)于reserve的深度剖析

眾所周知,reserve只改變capacity大小
而不會(huì)改變size的大小

所以這樣寫代碼是有問(wèn)題的:

vector<int> vv;
vv.reserve(10);//開(kāi)辟10份空間
for(int i=0;i<10;i++)
{
	vv[i]=i;
}

因?yàn)閟ize此時(shí)是0,也就是有效長(zhǎng)度為0
雖然你開(kāi)辟了10份空間,但是運(yùn)算符
操作[ ]的內(nèi)部實(shí)現(xiàn)會(huì)檢查下標(biāo):

T& operator[](size_t pos)
{
	assert(pos < size());
	return _start[pos];
}

所以使用reserve后直接用[ ]
訪問(wèn)會(huì)報(bào)錯(cuò),這也是很多人會(huì)出錯(cuò)的地方!


6. vector深淺拷貝問(wèn)題

首先來(lái)看看以下代碼:

vector<vector<int>> vv(3,vector<int>(5));

這是一個(gè)二維數(shù)組,初始化為三行五列

vector<vector<int>> vv(3,vector<int>(5));
vector<vector<int>> x(vv);

這是在拷貝構(gòu)造類對(duì)象x

自我實(shí)現(xiàn)的拷貝構(gòu)造使用的是memcpy:

Vector(const Vector<T>& v)
{
	assert(v._start && v._finish && v._endofsto);
	_start = new T[v.capacity()];//給size或capacity都可以
	memcpy(_start, v._start, sizeof(T) * v.size());
}

然而memcpy是逐個(gè)字節(jié)拷貝
當(dāng)數(shù)組是一維時(shí),用memcpy沒(méi)有問(wèn)題
但是當(dāng)數(shù)組是二維數(shù)組時(shí),會(huì)出錯(cuò)!

我們?cè)赩S上調(diào)試窗口的監(jiān)視查看地址信息:

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言

會(huì)發(fā)現(xiàn),雖然x的地址和vv的地址不同
但是vv中的迭代器和x中的迭代器
的地址是相同的也就是指向同一份空間

可以用下圖來(lái)理解這個(gè)過(guò)程:

【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析,C++從入門到精通,c++,java,開(kāi)發(fā)語(yǔ)言


7. vector深淺拷貝的解決方法

由于這種深淺拷貝問(wèn)題是因?yàn)閙emcpy
導(dǎo)致的,所以這里不能使用memcpy
只需要老實(shí)的使用一個(gè)for循環(huán)就能解決:

修改后的代碼:

Vector(const Vector<T>& v)
{
	assert(v._start && v._finish && v._endofsto);
	_start = new T[v.capacity()];//給size或capacity都可以
	//memcpy(_start, v._start, sizeof(T) * v.size()); //使用memcpy時(shí),數(shù)組是二維數(shù)組會(huì)發(fā)生問(wèn)題
	for (size_t i = 0; i < size(); i++)
	{
		_start[i] = v._start[i];
		_finish = _start + v.size();
	}
	_endofsto = _start + v.capacity();
}

直接使用等號(hào)=是外部和內(nèi)部都是
原來(lái)的一份拷貝,這樣就能解決問(wèn)題了


8. 總結(jié)以及拓展

vector的自我實(shí)現(xiàn)的目的不是
為了實(shí)現(xiàn)一個(gè)比庫(kù)中更好的vector
而是為了帶大家熟悉vector的使用
并且了解了內(nèi)部實(shí)現(xiàn)后,以后用vector
時(shí)出現(xiàn)問(wèn)題可以很快的排查出來(lái)!

拓展:vector自我實(shí)現(xiàn)全部代碼鏈接:

gitee代碼倉(cāng)庫(kù)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-682334.html


?? 下期預(yù)告:鏈表接口熟悉以及模擬實(shí)現(xiàn) ??

到了這里,關(guān)于【C++進(jìn)階(三)】STL大法--vector迭代器失效&深淺拷貝問(wèn)題剖析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題)

    【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題)

    送給大家一句話: 世界在旋轉(zhuǎn),我們跌跌撞撞前進(jìn),這就夠了 —— 阿貝爾 加繆 我們之前實(shí)現(xiàn)了手搓vector,但是當(dāng)時(shí)依然有些問(wèn)題沒(méi)有解決: 迭代器區(qū)間拷貝(非法的間接尋址問(wèn)題) 迭代器失效問(wèn)題 使用memcpy拷貝問(wèn)題 接下來(lái),我們一點(diǎn)一點(diǎn)來(lái)解決這些問(wèn)題!??! 來(lái)看這個(gè)

    2024年04月09日
    瀏覽(20)
  • 【C++】vector類的模擬實(shí)現(xiàn)(增刪查改,拷貝構(gòu)造,賦值運(yùn)算,深淺拷貝)

    【C++】vector類的模擬實(shí)現(xiàn)(增刪查改,拷貝構(gòu)造,賦值運(yùn)算,深淺拷貝)

    ??博客主頁(yè): 主頁(yè) ??系列專欄: C++ ??感謝大家點(diǎn)贊??收藏?評(píng)論?? ??期待與大家一起進(jìn)步! 我們模擬vector是用迭代器(start,end,endofstorage)來(lái)控制增刪查改操作的 1普通構(gòu)造 2迭代器構(gòu)造 3初始化字符構(gòu)造 4拷貝構(gòu)造: 1當(dāng)前大小(size()) 2總體容量(capacity()) 1begin()

    2024年02月15日
    瀏覽(19)
  • 【C++進(jìn)階(一)】STL大法以及string的使用

    【C++進(jìn)階(一)】STL大法以及string的使用

    ??博主CSDN主頁(yè):杭電碼農(nóng)-NEO?? ? ?專欄分類:C++從入門到精通? ? ??代碼倉(cāng)庫(kù):NEO的學(xué)習(xí)日記?? ? ??關(guān)注我??帶你學(xué)習(xí)C++ ? ???? 由于C語(yǔ)言的 標(biāo)準(zhǔn)庫(kù)不夠強(qiáng)大 沒(méi)有數(shù)據(jù)結(jié)構(gòu)和一些基本算法 什么都需要程序員自己實(shí)現(xiàn) 所以C語(yǔ)言在某種意義上并不實(shí)用 本章重點(diǎn): 本章會(huì)

    2024年02月11日
    瀏覽(25)
  • 【C++】vector模擬實(shí)現(xiàn)+迭代器失效

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

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

    2024年02月21日
    瀏覽(86)
  • 【C++】vector的使用 以及 迭代器失效問(wèn)題

    【C++】vector的使用 以及 迭代器失效問(wèn)題

    前言 經(jīng)過(guò)前面string的學(xué)習(xí),我們已經(jīng)掌握了許多string的類函數(shù),vector中許多類函數(shù)與string中的類函數(shù)使用起來(lái)相似,例如迭代器的使用在所有的容器中使用都一樣,這里我們不再介紹,下面我們學(xué)習(xí)一些vector類的一些常用的函數(shù)。 1.vector的文檔介紹 2. vector在C++中表示可變大

    2023年04月24日
    瀏覽(18)
  • 【C++進(jìn)階(六)】STL大法--棧和隊(duì)列深度剖析&優(yōu)先級(jí)隊(duì)列&適配器原理

    【C++進(jìn)階(六)】STL大法--棧和隊(duì)列深度剖析&優(yōu)先級(jí)隊(duì)列&適配器原理

    ??博主CSDN主頁(yè):杭電碼農(nóng)-NEO?? ? ?專欄分類:C++從入門到精通? ? ??代碼倉(cāng)庫(kù):NEO的學(xué)習(xí)日記?? ? ??關(guān)注我??帶你學(xué)習(xí)C++ ? ???? 和C語(yǔ)言學(xué)習(xí)期間的學(xué)習(xí)順序一樣 順序表,鏈表過(guò)了就是棧和隊(duì)列 但是棧和隊(duì)列非常特殊,它的內(nèi)部結(jié)構(gòu) 并不是靠自己實(shí)現(xiàn)的,而是一種 適配

    2024年02月08日
    瀏覽(28)
  • 【C++庖丁解?!縎TL之vector容器的介紹及使用 | vector迭代器的使用 | vector空間增長(zhǎng)問(wèn)題

    【C++庖丁解?!縎TL之vector容器的介紹及使用 | vector迭代器的使用 | vector空間增長(zhǎng)問(wèn)題

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

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

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

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

    2024年04月14日
    瀏覽(30)
  • 【C++入門到精通】C++入門 —— 深淺拷貝函數(shù)

    【C++入門到精通】C++入門 —— 深淺拷貝函數(shù)

    目錄 拷貝函數(shù) 淺拷貝拷貝構(gòu)造函數(shù) 深拷貝拷貝構(gòu)造函數(shù) 總結(jié) ? ? ? ? 前面我們學(xué)習(xí)了C++的一些基本的知識(shí)點(diǎn),并且介紹了一些STL里面String的一些關(guān)鍵操作,除了這些博主還新開(kāi)了一個(gè)專欄關(guān)于Linux的講解(Linux專欄鏈接)大家可以關(guān)注一下,后面我會(huì)一點(diǎn)一點(diǎn)的更新的。大

    2024年02月13日
    瀏覽(54)
  • 【C++】string類的深淺拷貝問(wèn)題

    【C++】string類的深淺拷貝問(wèn)題

    我們知道,定義一個(gè)類的時(shí)候,如果我們沒(méi)有寫構(gòu)造,拷貝構(gòu)造,賦值運(yùn)算符重載,析構(gòu)方法的話,編譯器會(huì)自動(dòng)生成。當(dāng)該類成員中涉及到資源的管理時(shí),實(shí)現(xiàn)的就是淺拷貝。所以,以上這幾種方式是必須要程序猿手動(dòng)實(shí)現(xiàn)的。 舉例來(lái)看: 圖中所示:實(shí)現(xiàn)了構(gòu)造和析構(gòu),

    2023年04月26日
    瀏覽(23)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包