C++面試八股文:std::vector瞭解嗎?

2023-06-24 06:00:44

某日二師兄參加XXX科技公司的C++工程師開發崗位第23面:

面試官: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)對齊,達到釋放記憶體的作用:

#include <iostream>
#include <vector>
int main(int argc, char const *argv[])
{
    std::vector<int> vi;
    vi.reserve(1024);
    for (int i = 0; i < 1024; i++) vi.push_back(i);
    std::cout << vi.size() << " " << vi.capacity() << std::endl;    //1024 1024
    vi.clear(); 
    std::cout << vi.size() << " " << vi.capacity() << std::endl;    //0 1024
    vi.shrink_to_fit(); 
    std::cout << vi.size() << " " << vi.capacity() << std::endl;    //0 0
}

二師兄:第二種,使用swap方法;

#include <iostream>
#include <vector>
int main(int argc, char const *argv[])
{
    std::vector<int> vi;
    vi.reserve(1024);
    for (int i = 0; i < 1024; i++) vi.push_back(i);
    std::cout << vi.size() << " " << vi.capacity() << std::endl;    //1024 1024
    std::vector<int>().swap(vi); //使用臨時量(size =0, capacity=0)和vi交換,臨時量會立即解構
    std::cout << vi.size() << " " << vi.capacity() << std::endl;    //0 0
}

面試官:你知道vector<bool>是如何實現的嗎?

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

面試官:好的,回去等通知吧。

今天二師兄表現不錯,同時要感謝小夥伴的耐心閱讀。讓我們一起期待明天二師兄的面試之旅吧。

關注我,帶你21天「精通」C++!(狗頭)