中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++?Vector迭代器失效問題如何解決

發布時間:2022-08-03 17:51:05 來源:億速云 閱讀:155 作者:iii 欄目:開發技術

本篇內容主要講解“C++ Vector迭代器失效問題如何解決”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++ Vector迭代器失效問題如何解決”吧!

一、迭代器失效

主要作用就是讓算法能夠不用關心底層數據結構,其底層實際就是一個指針,或者是對指針進行了封裝。比如:vector的迭代器就是原生態指針T*。因此迭代器失效,實際就是迭代器底層對應指針所指向的空間被銷毀了,而使用一塊已經被釋放的空間,造成的后果是程序崩潰(即如果繼續使用已經失效的迭代器,程序可能會崩潰)。

二、可能引起的迭代器失效的操作

2.1、野指針引起迭代器失效

凡是涉及到擴容操作,都有可能引起迭代器失效,因為vector擴容是分配一個新的數組,然后全部元素移到新的數組中。

下面我們就以Insert函數來舉例說明!

示例1:

void test02()
{
	// 在所有的偶數的前面插入2
	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);
	cout << v.size() << ":" << v.capacity() << endl;
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
		{
			v.insert(it, 20);
			++it; //這里++是為了解決第二種迭代器失效,防止原地踏步
		}
		++it;
	}
	cout << v.size() << ":" << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

程序崩潰!

C++?Vector迭代器失效問題如何解決

代碼解釋:如果我們沒有預先分配空間,那么在insert的時候會發生擴容,根據我們模擬實現vector可知,STL標準庫的vector中insert函數是實現了對迭代器的更新,但是形參列表沒有使用輸出型參數,所以我們只有通過返回值來接收新的迭代器!

示例2:

如果我們用返回值來接受新的迭代器,則不會崩潰!

void test02()
{
	// 在所有的偶數的前面插入2
	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);
	cout << v.size() << ":" << v.capacity() << endl;
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
		{
			it = v.insert(it, 20);//stl中的insert如果發生了擴容是實現了對it位置的更新,并用返回值輸出了形參的改變
			++it; //這里++是為了解決第二種迭代器失效,防止原地踏步
		}
		++it;
	}
	cout << v.size() << ":" << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

6:6
9:9
1 20 2 3 20 4 5 20 6
請按任意鍵繼續. . .

代碼解釋:

STL中的insert如果發生了擴容是實現了對it位置的更新,并用返回值輸出了形參的改變。

示例3:

如果我們預先預留(reserve)了空間,再插入過程中沒發生擴容,那么自然也不會失效了。

void test02()
{
	// 在所有的偶數的前面插入2
	vector<int> v;
	v.reserve(20);
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);
	cout << v.size() << ":" << v.capacity() << endl;
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
		{
			//it = v.insert(it, 20);
			v.insert(it, 20);
			++it; 
		++it;
	}
	cout << v.size() << ":" << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

2.2、迭代器指向的位置意義改變

一般vector刪除數據,都不考慮縮容的方案。縮容方案: size() < capacity()/2時,可以考慮開一個size()大小的空間,拷貝數據,釋放舊空間。縮容方案本質是時間換空間。一般設計都不會考慮縮容,因為實際比較關注時間效率,不關注空間效率,因為現在硬件設備空間都比較大,空間存儲也比較便宜。

示例4:

void test03(){
	vector<int> v;
	cout << v.size() << ":" << v.capacity() << endl;
	v.reserve(10);
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	cout << v.size() << ":" << v.capacity() << endl;
	auto pos = find(v.begin(), v.end(), 2);
	if (pos != v.end())
	{
		v.erase(pos);
	}
	cout << v.size() << ":" << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	cout << *pos << endl; //只要一訪問 系統強制檢查(怎么檢查的不知道!), 就報錯(Linux沒報錯)
	*pos = 10;
	cout << *pos << endl << endl;
}

C++?Vector迭代器失效問題如何解決

代碼解釋:可見代碼確實是實現了刪除,但是程序卻崩了,原因就是erase后pos失效了,pos的意義變了,(但是在不同平臺下對于訪問pos的反應是不一樣的,因此我們使用的時候要特別小心,統一以失效的角度去看待)。但如果不訪問pos指向的內容就不會崩潰!

erase導致的失效:

  • erase失效都是意義變了。

  • 一般不會有縮容方案,那么erase的失效,一般也不存在野指針的失效。

下面我們舉個實例:

要我們刪除容器中所有偶數:

示例5:

void test05()
{
	std::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(2);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(4);
	v.push_back(4);
	v.push_back(5);
	auto it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
		{
			v.erase(it);//刪除了就不移動
		}
		else
		{
			++it;
		}
	}
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

C++?Vector迭代器失效問題如何解決

代碼解釋:毫無疑問上訴代碼會崩潰,因為erase后迭代器it所指向的位置失效,(雖然感覺是可以繼續使用的,但在vs下就是不可以使用,在Linux下就可以對這個位置進行訪問),所以下面我們用返回值來更新迭代器。

示例6:

void test05()
{
	std::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(2);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(4);
	v.push_back(4);
	v.push_back(5);
	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;
}

1 3 5
請按任意鍵繼續. . .

代碼解釋:可見成功的刪除了其中的偶數!

其中緣由:erase刪除pos位置元素后,pos位置之后的元素會往前移動,沒有導致底層空間的改變,理論上講迭代器不會失效,但是如果pos位置剛好是最后一個元素,刪完之后pos剛好是end的位置,而end的位置是沒有有效元素的,那么pos就失效了。因此刪除vector中任意位置元素時,vs均認為該位置上迭代器失效了!

除erase導致意義失效外,insert也可能導致意義失效,但是編譯器卻檢查不出來!!!

示例7:

void test01(){
	vector<int> v;
	cout << v.size() << ":" << v.capacity() << endl;
	v.reserve(10);
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	cout << v.size() << ":" << v.capacity() << endl;
	auto pos = find(v.begin(), v.end(), 2);
	if (pos != v.end())
	{
		v.insert(pos, 20);
	}
	cout << v.size() << ":" << v.capacity() << endl;
	cout << *pos << endl;
	*pos = 10;
	cout << *pos << endl << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

0:0
4:10
5:10
20
10

1 10 2 3 4

代碼解釋:同樣地,不是因為擴容而引起的意義失效,這個時候我們訪問了pos指向的位置,編譯器卻不報錯,但此時并不意味著一定對,后續如果進一步操作,還是會發生各種各樣的錯誤!

到此,相信大家對“C++ Vector迭代器失效問題如何解決”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

酒泉市| 明溪县| 新邵县| 连平县| 花莲县| 蚌埠市| 三江| 淮阳县| 永清县| 沾益县| 定远县| 察隅县| 满洲里市| 保山市| 凤城市| 新兴县| 随州市| 施秉县| 米泉市| 山东| 乌兰察布市| 和田县| 宽城| 弥渡县| 盐边县| 嘉禾县| 湘潭县| 余姚市| 西乌| 当雄县| 普宁市| 崇义县| 霍林郭勒市| 达尔| 崇州市| 长宁区| 泽库县| 湖南省| 恭城| 沈丘县| 西安市|