C++ vector使用的一些注意事項(xiàng)
1. 初始化
c++ 11以后新增了大括號(hào){}的初始化方式,需要注意與()的區(qū)別,如:
std::vector<int> vecTest1(5); //初始化5個(gè)元素,每個(gè)都是0
std::vector<int> vecTest2{ 5 }; //初始化1個(gè)元素,值是5
2. 添加元素:push_back
通過push_back添加新的元素進(jìn)入vector后,vector的內(nèi)存有時(shí)候會(huì)發(fā)生變化,這取決于size和capacity大小,當(dāng)然這些都是系統(tǒng)來處理的,詳細(xì)可以參考stl源碼
當(dāng)size<capacity的時(shí)候,直接加到末尾,不會(huì)變化
當(dāng)size==capacity的時(shí)候,會(huì)重新申請(qǐng)另外一塊內(nèi)存,然后copy過去加到尾部,這個(gè)時(shí)候就會(huì)有變化了。
對(duì)于stl的容器,都有成員:
begin() //起始位置
end() //結(jié)束位置
size() //當(dāng)前大小
capacity() //當(dāng)前容量,即已申請(qǐng)的內(nèi)存大小
vector是一段連續(xù)的內(nèi)存空間,有三個(gè)標(biāo)識(shí)內(nèi)存的位置,start,end,finish, size=end-start, capacity=finish-start
很多時(shí)候在使用vector的時(shí)候,會(huì)看到size=capacity,這個(gè)時(shí)候直接添加元素到尾部,內(nèi)存明顯是不夠的,此時(shí)會(huì)重新在別處分配一塊大小足夠
有時(shí)候也有size<capacity, 這個(gè)時(shí)候就直接加在尾部了。
std::cout << "vecNum push back init" << std::endl; vector<int> vecNum(5); std::cout << "vecNum addr: " << &vecNum << std::endl; for(auto i = 5; i < 10; i++) { vecNum.push_back(i*10); std::cout << "vecNum push_back(" << i << ")=" << i*10 << std::endl; std::cout << "vecNum.size() = " << vecNum.size() << ",vecNum.capacity() = " << vecNum.capacity() << std::endl; std::cout << "vecNum.begin() addr: " << &(*vecNum.begin()) << std::endl; } std::cout << "vecNum addr: " << &vecNum << std::endl;
3. 關(guān)于earse和remove
erase返回的是當(dāng)前刪除的元素的一下個(gè)位置的迭代器,所以需要注意的是遍歷時(shí)候的++運(yùn)算,這個(gè)與其它list,map差不多,
需要注意的earse后內(nèi)存并未真正的清空,僅僅是刪除內(nèi)容,真正的容量大小capacity并沒有改變,需要通過swap來實(shí)現(xiàn)capacity的減小
全部清空可以考慮:vector<int>().swap(vecNum);
auto itor = vecNum.begin(); for( ; itor != vecNum.end(); ) { auto num = *itor; if(num == 60) { itor = vecNum.erase(itor); break; } else { itor++; } } std::cout << "after erase element 60:" << std::endl; printVector(vecNum); vector<int>(vecNum).swap(vecNum); //將vecNum的內(nèi)存空洞清除 printVector(vecNum);
//remove只是通過迭代器的指針向前移動(dòng)來刪除,將不需要?jiǎng)h除的元素往前移,因此需要?jiǎng)h除的就都在尾部了
//返回新的指向尾部需要?jiǎng)h除的元素的迭代器
因此還是得配合earse來使用,所以一般真要?jiǎng)h除,建議直接遍歷使用earse
auto itor = remove_if(vecNum.begin(), vecNum.end(),[](int x)->bool{ return x == 20; }); //or //auto itor = remove(vecNum.begin(), vecNum.end(),20); //通過erase刪除 vecNum.erase(itor, vecNum.end());
4. 關(guān)于vector< bool> -- 慎用
出處: http://www.dbjr.com.cn/article/167636.htm
vector< bool> 并不是一個(gè)STL容器,不是一個(gè)STL容器,不是一個(gè)STL容器!
首先vector< bool> 并不是一個(gè)通常意義上的vector容器,這個(gè)源自于歷史遺留問題。
早在C++98的時(shí)候,就有vector< bool>這個(gè)類型了,但是因?yàn)楫?dāng)時(shí)為了考慮到節(jié)省空間的想法,所以vector< bool>里面不是一個(gè)Byte一個(gè)Byte儲(chǔ)存的,它是一個(gè)bit一個(gè)bit儲(chǔ)存的!
因?yàn)镃++沒有直接去給一個(gè)bit來操作,
所以用operator[]的時(shí)候, 正常容器返回的應(yīng)該是一個(gè)對(duì)應(yīng)元素的引用,
但是對(duì)于vector< bool>實(shí)際上訪問的是一個(gè)”proxy reference”而不是一個(gè)”true reference”,返回的是”std::vector< bool>:reference”類型的對(duì)象。
因此,使用auto自動(dòng)類型推導(dǎo)時(shí)會(huì)出現(xiàn)問題
//vector<bool>慎用 vector<bool> vecBool = { false, true, false }; bool test1 = vecBool[0]; auto test2 = vecBool[1]; test1 = true; //test1的初始化它其實(shí)暗含了一個(gè)隱式的類型轉(zhuǎn)換(直接對(duì)vecBool[0]賦值會(huì)修改vecBool中的值,但是對(duì)test1不會(huì)) test2 = false; //test2它的類型并不是bool,而是一個(gè)vector< bool>中的一個(gè)內(nèi)部類,而此時(shí)如果修改test2的值,vecBool中的值也會(huì)跟著修改 auto index = 0; for (auto i : vecBool) { cout << "vecBool[" << index << "]" << i << std::endl; index++; }
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(88.混合插入有序數(shù)組)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(88.混合插入有序數(shù)組),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)解決方法
本篇文章是對(duì)在Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05詳解C++中的指針結(jié)構(gòu)體數(shù)組以及指向結(jié)構(gòu)體變量的指針
這篇文章主要介紹了C++中的指針結(jié)構(gòu)體數(shù)組以及指向結(jié)構(gòu)體變量的指針的用法,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09stl容器set,map,vector之erase用法與返回值詳細(xì)解析
在使用 list、set 或 map遍歷刪除某些元素時(shí)可以這樣使用,如下所示2013-09-09OpenCV和C++實(shí)現(xiàn)圖像的翻轉(zhuǎn)(鏡像)、平移、旋轉(zhuǎn)、仿射與透視變換
這篇文章主要給大家介紹了關(guān)于OpenCV和C++實(shí)現(xiàn)圖像的翻轉(zhuǎn)(鏡像)、平移、旋轉(zhuǎn)、仿射與透視變換的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09C++實(shí)現(xiàn)自定義撤銷重做功能的示例代碼
在使用c++做界面開發(fā)的時(shí)候,尤其是實(shí)現(xiàn)白板功能時(shí)需要自己實(shí)現(xiàn)一套撤銷重做功能.如果是qt則有QUndoable對(duì)象,可以直接拿來用。但是如果是使用gdi繪圖,則可能需要自己實(shí)現(xiàn)了。本文就來用C++實(shí)現(xiàn)自定義撤銷重做功能,需要的可以參考一下2022-12-12