C++基礎知識面試必備、複習細節 (6) (容器、lambda函數)

C++基礎知識面試必備、複習細節 (6)

常見的順序容器
順序容器類型 特點
vector 可變大小的數組。支持快速隨機訪問。在尾部之外的位置插入或刪除元素代價較高
list 雙向鏈表。支持雙向順序訪問。任意位置的插入刪除都效率較高,不支持快速訪問
forward_list 單向鏈表。支持單向順序訪問,任意位置插入刪除效率較高。
string 可變大小的保存字符的容器。支持快速隨機訪問。尾部插入刪除速度快
array 固定大小數組。支持快速隨機訪問。不能添加或刪除元素
deque 雙端隊列。支持快速隨機訪問,頭尾插入較快。
  • 通常使用vector,除非有更好的理由選擇其他容器

  • 如果程序需要在容器中間插入刪除,使用list或forward_list效率較高

  • 如果程序需要隨機訪問元素,則使用vector或deque較好

  • 迭代器的範圍: [begin,end),即begin代表第一個元素,而end是最後一個元素之後的一個元素

  • vector的初始化:vector<int>爲例

    vector<int> a; //默認構造函數
    vector<int> a(10); //初始化size爲10的vector
    vector<int> a(10,1); //10個元素,初始值均爲1
    vector<int> a{1,2,3,4,5}; //初始化列表拷貝
    
  • array的初始化

    array<int,40> a; //大小爲40的int數組
    array<int,10> b={1}; //第一個元素爲1,其餘爲0
    //內置數組不支持拷貝或賦值,但是array支持,只需要操作合法即可
    array<int,10> c={0,1,2,3,4,5,6,7,8,9};
    array<int,10> d=c;
    
vector對象是如何增長的
  • vector支持快速隨機訪問元素,因此必須將元素連續存儲,又支持容量動態改變

  • vector實現時記錄有兩個大小:size 和 capacity

    size是已經保存的元素的數目,capacity是在不分配新的內存空間的前提下最多能容納的元素數量

       vector<int> f(5,1);
       cout << f.size()<<' '<<f.capacity()<<' ';   // 5,5
       f.push_back(1);
       cout << f.size() << ' ' << f.capacity() << ' '; //6 10
    
  • Vector通過一個連續的數組存放元素,如果集合已滿,在新增數據的時候,就要分配一塊更大的內存,將原來的數據複製過來,釋放之前的內存,在插入新增的元素

  • 不同的編譯器實現的擴容方式不一樣,VS2015中以1.5倍擴容,GCC以2倍擴容。

  • 擴容倍數實際上是時間和空間的一種權衡,當倍數大時對空間浪費嚴重,倍數小時可能導致頻繁的擴容。

string的一些方法
  • s.substr(pos,n) 返回一個字符串,返回s中從pos開始的n個字符串的拷貝
  • s.insert(pos,args) 在pos之前插入args制定的字符,pos爲下標或迭代器
  • s.find(s1) 在s中查找s1,如果有返回第一個匹配位置的下標,否則返回 npos
  • s.compare(s1) 比較兩個字符串,判斷s是否等於、大於或小於s1,返回0、正數或負數
  • to_string(T a) 將a轉換爲string類型返回,通常轉換的是數值類型
容器適配器
容器適配器名稱 特點
stack 先入後出。頭文件 <stack> top()返回棧頂部元素 push()加入元素 pop()刪除元素
queue 先入先出。頭文件<queue> front()返回隊列首元素 back()返回隊列尾元素 push()加入元素 pop()刪除元素
priority_queue 帶優先級的隊列。根據設立的優先級規則進行隊列的排序。 頭文件<queue> 默認是最大堆 push()加入元素 pop()刪除元素
priority_queue<Type, Container, Functional>
//
priority_queue <int,vector<int>,greater<int> > q;  //最小堆
priority_queue <int,vector<int>,less<int> > q;  //最大堆
常用的泛型算法
  • find(vec.cbegin(),vec.cend(),val) 如果val出現在vec中,則返回第一次出現的位置,否則返回vec.end()
  • accumulate(vec.cbegin(),vec.cend(),val) 返回vec中元素的和,val爲sum的初值
  • fill(vec.begin(),vec.end(),val) 將每個元素都填爲val
  • sort(vec.begin(),vec.end(),cmp) 排序vec ,可以重寫cmp
lambda表達式
  • C++ 11 中的 Lambda 表達式用於定義並創建匿名的函數對象,簡化編程工作

  • lambda表達式常用於algorithm庫中的一些泛型函數的參數

  • lambda的語法:

    [capture list] (parameter list)-> return type{function body}
    //capture list:捕獲列表	 lambda所在函數中定義的局部變量列表
    //paremeter list:形參列表
    //return type:返回類型
    //function body:函數體
    
  • 可以忽略參數列表和返回類型,但必須永遠包含捕獲列表和函數體

  • 寫一個lambda函數來調用sort從大到小排序

        vector<int> nums{1,3,2,5,4};
        sort(nums.begin(), nums.end(), [](int a1,int a2) { return a1 > a2; });
        for(auto &i:nums)
            cout << i << ' ';
    	//5,4,3,2,1
    
  • 用lambda函數作爲for_each的參數執行操作

        vector<int> nums{1,3,2,5,4};
        sort(nums.begin(), nums.end(), [](int &a1,int &a2) { return a1 > a2; });
        for_each(nums.begin(), nums.end(), [](int &a) { cout << a << ' '; });
    
  • 注意lambda函數的值捕獲與引用捕獲

    //---------------引用捕獲----------- 
     	int a = 1;
        auto f2 = [&a] { return a; };
        a = 0;
        auto j = f2();
        cout << j << endl;   //輸出爲0,因爲捕獲的a發生了變化將隨之變化
    //----------------值捕獲-------------
        int a = 1;
        auto f2 = [a] { return a; };
        a = 0;
        auto j = f2();
        cout << j << endl;   //輸出爲1,在a改爲0之前其值已經被拷貝並捕獲,a發生變化不影響
    

    因此如果希望在lambda函數中修改局部變量的值,則使用引用捕獲

  • 可以通過將捕獲列表的值設爲 = , 則將值捕獲所有的該函數可見的局部變量;

    ​ 將捕獲類別的值設爲 &,則將引用捕獲所有的函數可見的局部變量

  • 默認情況下,如果一個lambda體包含return之外的任何語句,則編譯器認爲該lambda返回爲空

    //兩個函數等價
    [](int i){return i<0?-i:i;};
    [](int i)->int{if(i<0) return -i;else return i;}; //必須聲明返回->int
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章