Effective STL 學習筆記 Item 17: Swap Trick

假設有若干對象存於一個 vector 中:html

class Widget;
vector<Widget> vw;

後來因爲某些緣由,從該容器中刪除了若干對象(參考erase-remove idiom )。對於 vector 和 string 來說, erase()clear() 並不會改變容器的capacity,也就不會改變他們的內存佔用。java

swap() 本意是用來交換兩個容器的內容( Iterators, pointers, and references),但咱們能夠用他來快速將容器的 capacity 調整爲 合適 的大小:ios

vector<Widget>(vw).swap(vw);

巧妙之處在於, vector 的拷貝構造函數僅僅拷貝有用的部分而忽略那些未佔用的空間,用這個拷貝構造出來的容器來和 vw 進行 swap() 就能夠調整 vw 的 capacity 爲一個 相對較小的值c++

這裏之因此說是 相對較小的值 而不是與 size() 絕對相等,是由於容器的 Implementation 在構造的時候會本身選取合適的值來保證分配的空間足夠容納全部的元素,但這個值可能會比 size() 大, 可參考Item 14sql

下面是一個簡單的例子,對 vector 進行一些操做,而後輸出其 erase, swap,clear 以後的 size 與 capacity:bash

#include <vector>
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <fstream>
#include <iterator>

using namespace std;

const int MAX = 1024;

#define show(v, msg)    printf ("%s -- %s: size: %lu, capacity: %lu\n", \
                                #v, msg, v.size(), v.capacity());

int main(int argc, char *argv[])
{
    srand(time(NULL));

    printf("Testing vector...\n");
    vector<int> v;
    show(v, "After init");

    v.reserve(MAX);
    show(v, "After reserve()");

    for (int i = 0; i < MAX; ++i)
    {
        v.push_back(random()%1000);
    }
    show(v, "After Filling");

    v.erase(remove_if(v.begin(), v.end(), [](int x){return x > 100;}), v.end());
    show(v, "After erase()");

    vector<int>(v).swap(v);
    show(v, "After swap()");

    v.clear();
    show(v, "after clear");

    vector<int>().swap(v);
    show(v, "after swap with empty vector");

    return 0;
}

其輸出以下:dom

Testing vector...
v -- After init: size: 0, capacity: 0
v -- After reserve(): size: 0, capacity: 1024
v -- After Filling: size: 1024, capacity: 1024
v -- After erase(): size: 106, capacity: 1024
v -- After swap(): size: 106, capacity: 106
v -- after clear: size: 0, capacity: 106
v -- after swap with empty vector: size: 0, capacity: 0
Program ended with exit code: 0
相關文章
相關標籤/搜索