你知道vector底層是如何實現的嗎?

你知道vector底層是如何實現的嗎?

vector底層使用動態數組來存儲元素對象,同時使用sizecapacity記錄當前元素的數量和當前動態數組的容量。如果持續的push_back(emplace_back)元素,當size大于capacity時,需要開辟一塊更大的動態數組,并把舊動態數組上的元素搬移到當前動態數組,然后銷毀舊的動態數組。

你知道新開辟的動態數組的容量是就數組的多少倍比較合適?

這個值在不同的編譯器上不是固定的。MSVC 是1.5,而GCC是2。

有沒有什么好的辦法提升vector連續插入效率?

如果知道數據的大概量,我們可以使用reserve方法直接為vector擴容這個量級。這樣在后續的數據插入時就不會因為頻繁的capacity被用盡而導致的多次的數據搬移,從而提升vector插入效率。

push_backemplace_back有什么區別?

兩者都可以在容器尾部插入元素。在GCC中,如果插入的元素是右值,兩者都會move元素到容器。如果是左值,兩者都會copy元素到容器。唯一不同的一點是,當C++版本高于C++17時,emplace_back返回當前插入的值的引用,而push_back返回void

eraseremove有什么區別?

erase屬于成員函數,erase刪除了元素,remove屬于算法庫函數,而remove只會把元素移動到尾部。

哪些情況下迭代器會失效?

迭代器失效主要有兩種情況引起:

1.插入數據。由于插入數據可能導致數據搬移(size > capacity),所以迭代器失效。

2.刪除數據。當使用erase刪除數據時,被刪除數據后面的數據依次向前移一位。這會導致被刪除數據之后的迭代器失效。

如何快速的清空vector容器并釋放vector容器所占用的內存?

有兩種方法:

  • 第一種,使用clear方法清空所有元素。然后使用shrink_to_fit方法把capacitysize(0)對齊,達到釋放內存的作用;
  • 第二種,使用swap方法;
你知道vector<bool>是如何實現的嗎?

vector<bool>的實現和其他實現容器的實現不一致。**每個元素被當作一個位而不是一個字節存儲。**這導致我們不能直接訪問該元素,也無法對每個元素取地址(8個元素可能在同一個字節中存儲)。所以不建議使用vector<bool>,必要時可以使用std::bitset替代。

介紹三個和大小、容量與內存相關的函數:
  • 一個是_M_shrink_to_fit函數,可以使用這個函數將_M_finish和_M_end_of_storage之間的內存釋放掉,正好使分配的內存大小滿足vector中元素量。
  • 一個是reserve函數,可以使用這個函數控制整個vector容量的作用,避免重新分配內存,例如我們如果知道元素最多有80個,我們就可以使用v.reserve(80)來一次分配80個內存。但是值得注意的是這個函數不能用來縮減容量
  • 一個是resize函數,這個函數實際就是改變_M_start和_M_finish之間的相對位置,改變的是元素的個數,如果resize(n)的n小于當前個數就刪除元素,如果大于就追加默認函數生成的對象。
vector是怎么變長的
typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::insert(iterator __position, const value_type& __x)
{const size_type __n = __position – begin();//如果還有空位,插入到最后一個位置,相當于push_backif (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage&& __position == end()){_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x);++this->_M_impl._M_finish;}else{_M_insert_aux(__position, __x);}return iterator(this->_M_impl._M_start + __n);
}

當容量不足的時候,就是_M_insert_aux函數發揮的時候,進行容量的擴展,實現如下:

template<typename _Tp, typename _Alloc>
void vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x)
{//內存空間足夠if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage){_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,_GLIBCXX_MOVE(*(this->_M_impl._M_finish- 1)));++this->_M_impl._M_finish;//__position后的元素依次向后移動一個位置_GLIBCXX_MOVE_BACKWARD3(__position.base(),this->_M_impl._M_finish - 2,this->_M_impl._M_finish – 1);//目標地址賦值*__position = _Tp(std::forward<_Args>(__args)...);}else{//內存加倍const size_type __len =_M_check_len(size_type(1), "vector::_M_insert_aux");const size_type __elems_before = __position - begin();pointer __new_start(this->_M_allocate(__len));pointer __new_finish(__new_start);__try{//給position位置賦值_Alloc_traits::construct(this->_M_impl,__new_start + __elems_before,std::forward<_Args>(__args)...);__x);__new_finish = 0;//拷貝position位置前元素__new_finish = std::__uninitialized_move_if_noexcept_a(this->_M_impl._M_start, __position.base(),__new_start, _M_get_Tp_allocator());++__new_finish;//拷貝position位置后元素__new_finish= std::__uninitialized_move_if_noexcept_a(__position.base(), this->_M_impl._M_finish,__new_finish, _M_get_Tp_allocator());}__catch(...){if (!__new_finish)_Alloc_traits::destroy(this->_M_impl,__new_start + __elems_before);elsestd::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());_M_deallocate(__new_start, __len);__throw_exception_again;}//析構原vector所有元素std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,_M_get_Tp_allocator());//釋放原vector內存空間_M_deallocate(this->_M_impl._M_start,this->_M_impl._M_end_of_storage,this->_M_impl._M_start);//vector內存地址指向新空間this->_M_impl._M_start = __new_start;this->_M_impl._M_finish = __new_finish;this->_M_impl._M_end_of_storage = __new_start + __len;}
}

其中_M_check_len函數的實現如下:

size_type
_M_check_len(size_type __n, const char* __s) const
{if (max_size() - size() < __n)__throw_length_error(__N(__s));//如果n小于當前size,內存加倍,否則內存增長n。const size_type __len = size() + std::max(size(), __n);return (__len < size() || __len > max_size()) ? max_size() : __len;
}

可以發現vector內存分配策略并不是簡單的加倍,如果n小于當前size,內存加倍,否則內存增長n。

接著我們講一下vector怎么刪除元素。vector刪除元素的函數有以下幾個:

// 刪除某個位置上的元素,返回下一個元素的位置
erase(const_iterator __position)
// 刪除一個區間內的所有元素
erase(const_iterator __first, const_iterator __last)
// 清空所有元素
clear()
// 借助remove刪除與val相等的所有元素
erase(remove(begin(), end(), val), end());
// 借助remove_if刪除滿足某個條件的所有元素
erase(remove_if(begin(), end(), <lambda>), end());
vector使用陷阱
  • vector的函數除了at函數之外,都不拋出異常,如果要取元素的話,均需要判斷是否越界,不然會引發未知的錯誤;

  • vector的內存占用空間只增不減,在使用vector時要及時清除元素和回收內存,尤其是在static對象中使用vector保存元素時。vector提供的刪除元素的成員函數,只是調用元素的析構函數析構掉元素,已經分配的內存并不會收回;

  • 所有內存空間是在vector析構時候才能被系統回收。empty()用來檢測容器是否為空的,clear()可以清空所有元素。但是即使clear(),vector所占用的內存空間依然如故,無法保證內存的回收。

  • 如果需要空間動態縮小,可以考慮使用deque。如果非vector不可,可以用swap()來幫助你釋放內存。具體方法如下:

  • 如果vector中存放的是指針,那么當vector銷毀的時候,這些指針指向的對象不會被銷毀,所占用的內存也不會被釋放。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/711612.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/711612.shtml
英文地址,請注明出處:http://en.pswp.cn/news/711612.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【InternLM 實戰營筆記】XTuner 大模型單卡低成本微調實戰

XTuner概述 一個大語言模型微調工具箱。由 MMRazor 和 MMDeploy 聯合開發。 支持的開源LLM (2023.11.01) InternLM Llama&#xff0c;Llama2 ChatGLM2&#xff0c;ChatGLM3 Qwen Baichuan&#xff0c;Baichuan2 Zephyr 特色 傻瓜化&#xff1a; 以 配置文件 的形式封裝了大…

WebGIS----wenpack

學習資料&#xff1a;https://webpack.js.org/concepts/ 簡介&#xff1a; Webpack 是一個現代化的 JavaScript 應用程序的模塊打包工具。它能夠將多個 JavaScript 文件和它們的依賴打包成一個單獨的文件&#xff0c;以供在網頁中使用。 Webpack 還具有編譯和轉換其他類型文…

自學新標日第六課(單詞部分 未完結)

第六課 單詞 單詞假名聲調詞義來月らいげつ1下個月先月せんげつ1上個月夜中よなか3午夜昨夜ゆうべ0昨天晚上コンサートこんさーと1音樂會クリスマスくりすます3圣誕季誕生日たんじょうび&#xff13;生日こどもの日こどものひ&#xff15;兒童節夏休みなつやすみ&#xff13;…

看待事物的層與次 | DBA與架構的一次對話交流

前言 在計算機軟件業生涯中,想必行內人或多或少都能感受到系統架構設計與數據庫系統工程的重要性,也能夠清晰地認識到在計算機軟件行業中技術工程師這個職業所需要的專業素養和必備技能! 背景 通過自研的數據庫監控管理工具,發現 SQL Server 數據庫連接數在1-2K之間,想…

Yii2中如何使用scenario場景,使rules按不同運用進行字段驗證

Yii2中如何使用scenario場景&#xff0c;使rules按不同運用進行字段驗證 當創建news新聞form表單時&#xff1a; 添加新聞的時候執行create動作。 必填字段&#xff1a;title-標題&#xff0c;picture-圖片&#xff0c;description-描述。 這時候在model里News.php下rules規則…

星座每日運勢 api接口

接口數據api 接口平臺&#xff1a;https://api.yuanfenju.com/ 開發文檔&#xff1a;https://doc.yuanfenju.com/zhanbu/yunshi.html 支持格式&#xff1a;JSON 請求方式&#xff1a;HTTP POST <?php//您的密鑰 $api_secret "wD******XhOUW******pvr"; //請…

利用coze 搭建“全功能“微信客服(2)

緊跟上篇 利用coze 搭建"全功能"微信客服&#xff08;1&#xff09;&#xff0c;不知道來龍去脈自行查閱 先表揚下coze: coze 是國內少數開放平臺之一&#xff0c;里面提供各種插件還可以開發工作流&#xff0c;讓你可以實現多模態全功能大模型 吐槽 沒有API開放接口…

國外最流行的是AI,國內最流行的是AI培訓教程

國外最流行的是AI&#xff0c;國內最流行的是AI培訓教程。 最近李一舟AI教程事件&#xff0c;驗證了這句話。 如今給客戶做方案項目里能加點AI色彩&#xff0c;立項的成功率都變大(特別是事業單位)。 正因如此&#xff0c;大家都在狂補AI的知識&#xff0c;不然肚子里沒點墨水&…

2024亞馬遜全球開店注冊前需要準備什么?

在2023年出海四小龍SHEIN、Temu、速賣通AliExpress、TikTok Shop快速增長擴張&#xff0c;成為了中國跨境賣家“逃離亞馬遜”的新選擇。但是&#xff0c;跨境電商看亞馬遜。當前&#xff0c;亞馬遜仍然是跨境電商行業的絕對老大&#xff0c;占有將近70%成以上的業務份額。 作為…

threejs顯示本地硬盤上的ply文件,通過webapi

由于ply文件是第三方提供的&#xff0c;threejs無法用絕路路徑的方式顯示ply 所以想通過webapi把ply通過url地址的方式給threejs 1.webapi部分 /// <summary>/// 獲取PLY文件/// </summary>/// <returns></returns>[HttpPost(Name "GetPly&qu…

分享fastapi低級錯誤

我是創建表的時候把__tablename__ 寫成__table__然后一直報這個錯誤

Android Activity跳轉詳解

在Android應用程序中&#xff0c;Activity之間的跳轉是非常常見的操作&#xff0c;通過跳轉可以實現不同界面之間的切換和交互。在本篇博客中&#xff0c;我們將介紹Android中Activity跳轉的相關知識&#xff0c;包括基本跳轉、傳遞參數、返回數據以及跳轉到瀏覽器、撥號應用和…

端游如何防破解

在2023年這個游戲大年中&#xff0c;諸多熱門大作涌現&#xff0c;作為世界級IP哈利哈利波特的衍生游戲——《霍格沃茨之遺》毫無懸念地成為2023年游戲圈的首款爆款作品&#xff0c;斬獲了一眾玩家的青睞。 在眾多光環的加持下&#xff0c;《霍格沃茨之遺》很快被著名游戲破解…

【每日前端面經】2024-03-01

題目來源: 牛客 MVVM怎么實現 MVVM分別指View、Model、ViewModel&#xff0c;View通過View-Model的DOM監聽器將事件綁定到Model上&#xff0c;而Model則通過Data Bindings來管理View中的數據&#xff0c;View-Model從中起到一個連接的作用 響應式: vue如何監聽data的屬性變化…

深入 Starknet 去中心化世界,探秘實用開發利器

Starknet 近期開放空投&#xff0c;面向 130 萬地址總量發放超 7 億枚 Token&#xff0c;讓 ECMP 早期貢獻者、GitHub 開源開發者、Starknet 用戶等各個層面的生態參與者都得以深度參與。 盛宴的背后&#xff0c;是 Starknet 正迎來發展的關鍵機遇。在今年以太坊坎昆升級的背景…

從別人的開源項目學習并吸收經驗,然后逐步搭建自己的Java項目是一個很好的學習方法

從別人的開源項目學習并吸收經驗&#xff0c;然后逐步搭建自己的Java項目是一個很好的學習方法。以下是一些建議的步驟&#xff0c;幫助你從0開始搭建并不斷完善自己的Java項目&#xff0c;直至達到高可靠、高穩定、高并發、高數據安全&#xff0c;并可以拆分為微服務的大型高質…

【漏洞復現】某廠商上網行為管理系統static_convert命令執行漏洞

Nx01 產品簡介 天融信上網行為管理系統是天融信公司憑借多年來的安全產品研發經驗&#xff0c;為滿足各行各業進行網絡行為管理和內容審計的專業產品。 Nx02 漏洞描述 天融信上網行為管理系統老版本static_convert.php接口存在RCE漏洞&#xff0c;攻擊者利用此漏洞可以獲取服務…

超強預測算法:XGBoost預測模型

目錄 往期精彩內容&#xff1a; 多變量特征序列、單序列數據預測實戰 前言 1 風速數據預處理與數據集制作 1.1 導入數據 1.2 多變量數據預處理與數據集制作 1.3 單序列數據預處理與數據集制作 2超強模型XGBoost——原理介紹 3 模型評估和對比 3.1 隨機森林預測模型 3…

基于NeRF/Gaussian的全新SLAM算法

什么是SLAM&#xff1f; SLAM&#xff0c;即同時定位與地圖構建技術&#xff0c;SLAM可以讓機器人、無人機和其他自動化系統能夠在未知環境中同時進行自我定位和環境映射。 為什么是NeRF-Based SLAM&#xff1f; 傳統CG將輸入圖像重新投影再融合到新的視圖攝像機中&#xff0c…

InfiniBand 200Gbps QSFP56 高速線纜/光纜和光模塊解決方案

隨著數據中心和人工智能迅速發展&#xff0c;對高速、低延遲和低功耗的數據傳輸需求變得至關重要。飛速&#xff08;FS&#xff09;提供針對各種高性能計算場景量身定制的各種InfiniBand線纜和光模塊產品。本文旨在概述飛速&#xff08;FS&#xff09;200G InfiniBand HDR 光纜…