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

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

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

【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題),從零開始的C++生活,c++,java,開發(fā)語(yǔ)言,算法,linux,學(xué)習(xí),藍(lán)橋杯
送給大家一句話:

世界在旋轉(zhuǎn),我們跌跌撞撞前進(jìn),這就夠了 —— 阿貝爾 加繆

1 前言

我們之前實(shí)現(xiàn)了手搓vector,但是當(dāng)時(shí)依然有些問(wèn)題沒有解決:

  1. 迭代器區(qū)間拷貝(非法的間接尋址問(wèn)題)
  2. 迭代器失效問(wèn)題
  3. 使用memcpy拷貝問(wèn)題

接下來(lái),我們一點(diǎn)一點(diǎn)來(lái)解決這些問(wèn)題?。?!

2 迭代器區(qū)間拷貝

來(lái)看這個(gè)這個(gè)構(gòu)造函數(shù):

		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

這個(gè)是對(duì)迭代器區(qū)間進(jìn)行的構(gòu)造函數(shù),思路很簡(jiǎn)單,把迭代器區(qū)間的數(shù)據(jù)依次尾插就可以了(這里之所以另外使用一個(gè)新的模版,而不是使用vector類的模版,是為了兼容更多的數(shù)據(jù)類型)。這樣就可以通過(guò)一個(gè)現(xiàn)有的類型來(lái)構(gòu)造容器。
但是出乎意料的是出現(xiàn)了一個(gè)問(wèn)題: C2100 非法的間接尋址 (編譯層面的問(wèn)題) 。非法的間接尋址的造成原因有很多:

  1. 空指針引I用:當(dāng)一個(gè)指針沒有被初始化或者為NULL時(shí),對(duì)它進(jìn)行間接尋址操作會(huì)導(dǎo)致非法訪問(wèn)。
  2. 野指針引用:當(dāng)一個(gè)指針超出了它所指向的內(nèi)存范圍,或者已經(jīng)被釋放但仍然被引用時(shí),進(jìn)行間接尋址操作也會(huì)導(dǎo)致非法訪問(wèn)。
  3. 類型不匹配:如果試圖將指針轉(zhuǎn)換為不兼容的類型進(jìn)行間接尋址,也會(huì)導(dǎo)致非法訪問(wèn)。

我們分析一下我們遇到的問(wèn)題是那種問(wèn)題?空指針引用嗎?不可能!野指針引用嗎?也不可能!??! 那么真相只有一個(gè):我們遇到了類型不匹配的問(wèn)題,那這是來(lái)自哪里的呢???,經(jīng)過(guò)我的排除法(注釋不同的代碼塊來(lái)進(jìn)行查找),得到了結(jié)果

vector<int> v1(5,6);

這一行代碼是我們出錯(cuò)的根源,為什么這個(gè)構(gòu)造沒有去使用vector(size_t n,T val = T()),而是使用我們的vector(InputIterator first, InputIterator last),因?yàn)榈诙€(gè)函數(shù)與(5,6)的類型更匹配,編譯器會(huì)尋找最合適的函數(shù)。

解決方法也是十分暴力:多枚舉幾個(gè) 構(gòu)造函數(shù):

vector(size_t n,T val = T())
vector(int n,T val = T());
vector(long long n,T val = T());

這樣就會(huì)優(yōu)先匹配vector(int n,T val = T());了,我們的問(wèn)題也就解決了。

3 迭代器失效問(wèn)題

這個(gè)問(wèn)題主要出現(xiàn)在我們的插入操作(insert)和刪除操作(erase)。來(lái)看:

void vector_test7() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);
	v1.push_back(7);


	vector<int>::iterator it = v1.begin() + 3;// 4
	cout << *it << endl;
	v1.insert(3, 40);
	cout << *it << endl;
}

這個(gè)執(zhí)行的結(jié)果是:
【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題),從零開始的C++生活,c++,java,開發(fā)語(yǔ)言,算法,linux,學(xué)習(xí),藍(lán)橋杯
迭代器的指向發(fā)生了改變,我們實(shí)現(xiàn)的迭代器的底層是指針,我們插入之后指針位置不變,而數(shù)組元素改變,自然會(huì)產(chǎn)生不一樣的結(jié)果。這個(gè)問(wèn)題看起來(lái)不嚴(yán)重,那我們?cè)賮?lái)看:

void vector_test7() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);
	v1.push_back(7);
	v1.push_back(8);

	vector<int>::iterator it = v1.begin() + 3;// 4
	cout << *it << endl;
	v1.insert(3, 40);
	cout << *it << endl;
}

【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題),從零開始的C++生活,c++,java,開發(fā)語(yǔ)言,算法,linux,學(xué)習(xí),藍(lán)橋杯
為什么這里出現(xiàn)了亂碼???我們代碼和之前的區(qū)別是什么???一個(gè)進(jìn)行了擴(kuò)容,一個(gè)沒進(jìn)行擴(kuò)容。擴(kuò)容之后vector的_start發(fā)生了改變,自然我們的指針也失去了對(duì)應(yīng)作用。 迭代器就失效了,這個(gè)解決辦法也很簡(jiǎn)單,就是插入之后不要使用之前的迭代器?。?!一定要對(duì)迭代器進(jìn)行更新。

再來(lái)看erase中的問(wèn)題:

void vector_test7() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	//v1.push_back(6);
	//v1.push_back(7);
	//v1.push_back(8);

	vector<int>::iterator it = v1.begin();
	//刪除偶數(shù)
	while (it != v1.end())
	{
		if (*it % 2 == 0)
		{
			v1.erase(it);
		}
		++it;
	}
	print_vector(v1);
}

這樣運(yùn)行起來(lái)是沒有問(wèn)題的,那么再來(lái)看:

void vector_test7() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(4);
	v1.push_back(5);
	//v1.push_back(6);
	//v1.push_back(7);
	//v1.push_back(8);

	vector<int>::iterator it = v1.begin();
	//刪除偶數(shù)
	while (it != v1.end())
	{
		if (*it % 2 == 0)
		{
			v1.erase(it);
		}
		++it;
	}
	print_vector(v1);
}

現(xiàn)在出現(xiàn)了:
【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題),從零開始的C++生活,c++,java,開發(fā)語(yǔ)言,算法,linux,學(xué)習(xí),藍(lán)橋杯
這個(gè)問(wèn)題,問(wèn)題的來(lái)源也很簡(jiǎn)單,我們迭代器在刪除之后沒有改變位置,但是_start的元素發(fā)生了改變,也就是相當(dāng)于 it 向后移動(dòng)了兩次,為了避免這個(gè)情況我們可以:

	while (it != v1.end())
	{
		if (*it % 2 == 0)
		{
			v1.erase(it);
		}
		else
		{
			++it;
		}
		
	}

這樣就可以了:
【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題),從零開始的C++生活,c++,java,開發(fā)語(yǔ)言,算法,linux,學(xué)習(xí),藍(lán)橋杯
需要注意的一點(diǎn)是,我們的操作是以g++標(biāo)準(zhǔn)來(lái)進(jìn)行的(如果刪除會(huì)進(jìn)行縮容,也會(huì)出現(xiàn)錯(cuò)誤,迭代器就不能進(jìn)行++了),所以 在VS環(huán)境下,vector 容器在erase 之后的迭代器是嚴(yán)格不能使用的,使用就會(huì)報(bào)錯(cuò),因?yàn)閂S迭代器的底層不是原生指針,判斷有所不同。
迭代器失效解決方案總結(jié)
1. 刪除插入之后更新對(duì)應(yīng)迭代器?。╡rase刪除后會(huì)返回新的迭代器 ,按規(guī)則進(jìn)行迭代就可以了 it = v1.erase(it)
2. 插入刪除之后不使用迭代器

4 memcpy拷貝問(wèn)題

我們創(chuàng)建一個(gè)string類的容器,來(lái)看看能不能正常運(yùn)行:

void vector_test8() {
	vector<string> v1;
	v1.push_back("11111");
	v1.push_back("22222");
	v1.push_back("33333");
	v1.push_back("44444");
	v1.push_back("55555");

	print_vector(v1);
}

來(lái)看效果:
【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題),從零開始的C++生活,c++,java,開發(fā)語(yǔ)言,算法,linux,學(xué)習(xí),藍(lán)橋杯程序直接崩掉了,經(jīng)過(guò)我們的調(diào)試,我們能打印出來(lái)正確的數(shù)據(jù),但是走到程序最后的時(shí)候出現(xiàn)了錯(cuò)誤,那么應(yīng)該就是析構(gòu)函數(shù)的問(wèn)題了!
來(lái)畫圖分析一波:

  1. memcpy是內(nèi)存的二進(jìn)制格式拷貝,將一段內(nèi)存空間中內(nèi)容原封不動(dòng)的拷貝到另外一段內(nèi)存空間中
  2. 如果拷貝的是自定義類型的元素,memcpy既高效又不會(huì)出錯(cuò),但如果拷貝的是自定義類型元素,并且自定義類型元素中涉及到資源管理時(shí),就會(huì)出錯(cuò),因?yàn)?strong>memcpy的拷貝實(shí)際是淺拷貝。
    【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(wèn)題),從零開始的C++生活,c++,java,開發(fā)語(yǔ)言,算法,linux,學(xué)習(xí),藍(lán)橋杯

結(jié)論:如果對(duì)象中涉及到資源管理時(shí),千萬(wàn)不能使用memcpy進(jìn)行對(duì)象之間的拷貝,因?yàn)閙emcpy是淺拷貝,否則可能會(huì)引起內(nèi)存泄漏甚至程序崩潰

那么怎么解決呢???非常簡(jiǎn)單:

		//擴(kuò)容
		void reserve(size_t newcapacity) {
			//記錄位置
			size_t n = _finish - _start;
			T* tmp = new T[newcapacity];
			//拷貝
			//memcpy(tmp, _start, size() * sizeof(T));
			for (size_t i = 0; i < size(); i++)
			{
				tmp[i] = _start[i];
			}
			delete[] _start;
			_start = tmp;
			_finish = _start + n;
			_end = _start + newcapacity;
			
		}

不使用memcpy函數(shù)不就可以了,然后我們使用簡(jiǎn)單粗暴的賦值拷貝,這樣就不會(huì)發(fā)生淺拷貝問(wèn)題了!??!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-845306.html

到了這里,關(guān)于【C++】vector問(wèn)題解決(非法的間接尋址,迭代器失效 , memcpy拷貝問(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++】list迭代器失效問(wèn)題

    【c++】list迭代器失效問(wèn)題

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

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

    C++筆記之迭代器失效問(wèn)題處理

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

    2024年02月14日
    瀏覽(15)
  • 嵌入式:ARM間接尋址、變址尋址與多寄存器尋址

    嵌入式:ARM間接尋址、變址尋址與多寄存器尋址

    寄存器間接尋址就是以寄存器中的值作為操作數(shù)的地址,而操作數(shù)本身存放在存儲(chǔ)器中。例如以下指令: 第一條指令將以R1的值為地址的存儲(chǔ)器中的數(shù)據(jù)傳送到R0中。第二條指令將R0的值傳送到以R1的值為地址的存儲(chǔ)器中。 ARM的數(shù)據(jù)傳送指令都是基于寄存器間接尋址,即通過(guò)

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

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

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

    2024年03月14日
    瀏覽(36)
  • C++中vector迭代器

    迭代器 (iterator)是一種用于遍歷數(shù)據(jù)集合的的對(duì)象。它提供了一種訪問(wèn)數(shù)據(jù)集合中元素的方式,而無(wú)需暴露數(shù)據(jù)集合內(nèi)部的細(xì)節(jié)。使用迭代器,我們可以對(duì)數(shù)據(jù)集合中的每個(gè)元素進(jìn)行處理,而無(wú)需將整個(gè)數(shù)據(jù)集合加載到內(nèi)存中。這樣可以節(jié)省內(nèi)存空間,并且在處理大型數(shù)據(jù)

    2024年02月11日
    瀏覽(16)
  • C++:關(guān)于模擬實(shí)現(xiàn)vector和list中迭代器模塊的理解

    C++:關(guān)于模擬實(shí)現(xiàn)vector和list中迭代器模塊的理解

    本篇是關(guān)于 vector 和 list 的模擬實(shí)現(xiàn)中,關(guān)于迭代器模塊的更進(jìn)一步理解,以及在前文的基礎(chǔ)上增加對(duì)于反向迭代器的實(shí)現(xiàn)和庫(kù)函數(shù)的對(duì)比等 本篇是寫于前面模擬實(shí)現(xiàn)的一段時(shí)間后,重新回頭看迭代器的實(shí)現(xiàn),尤其是在模板角度對(duì) list 中迭代器封裝的部分進(jìn)行解析,希望可以

    2024年02月07日
    瀏覽(23)
  • 【C++】反向迭代器的模擬實(shí)現(xiàn)通用(可運(yùn)用于vector,string,list等模擬容器)

    【C++】反向迭代器的模擬實(shí)現(xiàn)通用(可運(yùn)用于vector,string,list等模擬容器)

    ??博客主頁(yè): 主頁(yè) ??系列專欄: C++ ??感謝大家點(diǎn)贊??收藏?評(píng)論?? ??期待與大家一起進(jìn)步! 我們要寫出一個(gè)通用的反向迭代器模擬而且在保證代碼簡(jiǎn)介不繁瑣的的情況下,一定程度上使用我們自己模擬的已經(jīng)封裝好的iterator迭代器可以簡(jiǎn)化許多步驟,首先我們要知

    2024年02月14日
    瀏覽(28)
  • [STL-list]介紹、與vector的對(duì)比、模擬實(shí)現(xiàn)的迭代器問(wèn)題

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

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

    2024年04月15日
    瀏覽(24)
  • 【數(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日
    瀏覽(31)
  • 2.3 Vector 動(dòng)態(tài)數(shù)組(迭代器)

    2.3 Vector 動(dòng)態(tài)數(shù)組(迭代器)

    C++數(shù)據(jù)結(jié)構(gòu)與算法 目錄 1 C++自學(xué)精簡(jiǎn)教程 目錄(必讀) 2 VectorT 動(dòng)態(tài)數(shù)組(模板語(yǔ)法) 1 熟悉迭代器設(shè)計(jì)模式; 2 實(shí)現(xiàn)數(shù)組的迭代器; 3 基于迭代器的容器遍歷; 迭代器語(yǔ)法介紹 對(duì)迭代器的詳細(xì)介紹參考 : 迭代器 iterator 范圍for循環(huán) 刪除容器的元素 remove erase 迭代器的能力 迭

    2024年02月10日
    瀏覽(18)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包