std vector如何避免頻繁內(nèi)存創(chuàng)建

1. std vector中添加元素

In C++ vectors are dynamic arrays. Unlike arrays, they don’t have a fixed size. They can grow or shrink as required. Vectors are assigned memory in blocks of contiguous locations. When the memory allocated for the vector falls short of storing new elements, a new memory block is allocated to vector and all elements are copied from the old location to the new location. This reallocation of elements helps vectors to grow when required. However, it is a costly operation and time complexity is involved in this step is linear.

vector內(nèi)存不足的時候奶甘,會重新分配內(nèi)存block谬莹,而且會把之前已有的數(shù)據(jù)拷貝到新的內(nèi)存郭厌。這一系列操作是一個稍微耗時的操作,下面通過實際的例子說明赋元,

#include <iostream>
#include <vector>


class A {
public:
    A(int i) :i_(i) { std::cout << "ptr: [" << this << " ]" << " default ctor" << " i_= " << i_ << std::endl; }
    A(const A& x) {
        std::cout << "ptr: [" << this << " ]" << " copy ctor" << " i_= " << x.i_ << std::endl;
        i_ = x.i_;
    }
    ~A() {
        std::cout << "ptr: [" << this << " ]" << " dector" << " i_= " << i_ << std::endl;
    }
private:
    int i_;
};

int main() {
    std::vector<A> y;
    std::cout << "y.size()= " << y.size() << std::endl;
    //先生成A(1)臨時對象疑枯,然后在std::vector<A>中的構(gòu)造(拷貝構(gòu)造函數(shù))沦泌,然后A(1)臨時對象析構(gòu)
    y.push_back(A(1));
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(A(2));
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(A(3));
    std::cout << "y.size()= " << y.size() << std::endl;
    return 0;
};

程序輸出的結(jié)果溉痢,

y.size()= 0
ptr: [0000000B4D58FB74 ] default ctor i_= 1
ptr: [00000116C1FC0850 ] copy ctor i_= 1
ptr: [0000000B4D58FB74 ] dector i_= 1
y.size()= 1
ptr: [0000000B4D58FB78 ] default ctor i_= 2
ptr: [00000116C1FD1A14 ] copy ctor i_= 2
//00000116C1FC0850 又被拷貝到了 00000116C1FD1A10塘揣,之前的00000116C1FC0850又析構(gòu)
ptr: [00000116C1FD1A10 ] copy ctor i_= 1
ptr: [00000116C1FC0850 ] dector i_= 1
ptr: [0000000B4D58FB78 ] dector i_= 2
y.size()= 2
ptr: [0000000B4D58FB7C ] default ctor i_= 3
ptr: [00000116C1FD1BF8 ] copy ctor i_= 3
ptr: [00000116C1FD1BF0 ] copy ctor i_= 1
ptr: [00000116C1FD1BF4 ] copy ctor i_= 2
ptr: [00000116C1FD1A10 ] dector i_= 1
ptr: [00000116C1FD1A14 ] dector i_= 2
ptr: [0000000B4D58FB7C ] dector i_= 3
y.size()= 3
ptr: [00000116C1FD1BF0 ] dector i_= 1
ptr: [00000116C1FD1BF4 ] dector i_= 2
ptr: [00000116C1FD1BF8 ] dector i_= 3

從上面的結(jié)果我們能看出來包雀,

  1. 調(diào)用vectorpush_back(),先生成A(1)臨時對象亲铡,然后在std::vector<A>中的構(gòu)造(拷貝構(gòu)造函數(shù))才写,然后A(1)臨時對象析構(gòu)葡兑;
  2. 當(dāng)牽扯到內(nèi)存重新分配的時候,確實會把std::vector<A>中已有的元素重新復(fù)制到新的內(nèi)存赞草,例如結(jié)果中的多次調(diào)用拷貝構(gòu)造函數(shù)(copy ctor i_= 1)讹堤。

2. std move

在c++11中,標準庫新加了std::move厨疙,即移動語義洲守,它的一個作用是減少對象拷貝的開銷,具體少了多少沒細研究沾凄,這里僅貼出來代碼岖沛。

#include <iostream>
#include <vector>


class A {
public:
    A(int i) :i_(i) { std::cout << "ptr: [" << this << " ]" << " default ctor" << " i_= " << i_ << std::endl; }
    A(const A& x) {
        std::cout << "ptr: [" << this << " ]" << " copy ctor" << " i_= " << x.i_ << std::endl;
        i_ = x.i_;
    }
    A(const A&& x)noexcept {
        std::cout << "ptr: [" << this << " ]" << " move ctor" << " i_= " << x.i_ << std::endl;
        i_ = x.i_;
    }
    ~A() {
        std::cout << "ptr: [" << this << " ]" << " dector" << " i_= " << i_ << std::endl;
    }
private:
    int i_;
};

int main() {
    std::vector<A> y;
    //y.reserve(10);
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(std::move(A(1)));
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(std::move(A(2)));
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(std::move(A(3)));
    std::cout << "y.size()= " << y.size() << std::endl;
    return 0;
};

輸出結(jié)果如下,

y.size()= 0
ptr: [00000080C32FF914 ] default ctor i_= 1
ptr: [000001FA06440850 ] move ctor i_= 1
ptr: [00000080C32FF914 ] dector i_= 1
y.size()= 1
ptr: [00000080C32FF918 ] default ctor i_= 2
ptr: [000001FA06451A04 ] move ctor i_= 2
ptr: [000001FA06451A00 ] move ctor i_= 1
ptr: [000001FA06440850 ] dector i_= 1
ptr: [00000080C32FF918 ] dector i_= 2
y.size()= 2
ptr: [00000080C32FF91C ] default ctor i_= 3
ptr: [000001FA06451968 ] move ctor i_= 3
ptr: [000001FA06451960 ] move ctor i_= 1
ptr: [000001FA06451964 ] move ctor i_= 2
ptr: [000001FA06451A00 ] dector i_= 1
ptr: [000001FA06451A04 ] dector i_= 2
ptr: [00000080C32FF91C ] dector i_= 3
y.size()= 3
ptr: [000001FA06451960 ] dector i_= 1
ptr: [000001FA06451964 ] dector i_= 2
ptr: [000001FA06451968 ] dector i_= 3

和1中的輸出結(jié)果類似搭独,依然會牽扯內(nèi)存的移動(前面是拷貝)婴削。

3. 如何解決這個問題

std::vector class provides a useful function reserve which helps user specify the minimum size of the vector.It indicates that the vector is created such that it can store at least the number of the specified elements without having to reallocate memory.

可以利用reserve()函數(shù)告訴系統(tǒng)最少準備多少內(nèi)存牙肝,就不用來回分配內(nèi)存,多次創(chuàng)建、析構(gòu)了衡楞,如下所示,

#include <iostream>
#include <vector>


class A {
public:
    A(int i) :i_(i) { std::cout << "ptr: [" << this << " ]" << " default ctor" << " i_= " << i_ << std::endl; }
    A(const A& x) {
        std::cout << "ptr: [" << this << " ]" << " copy ctor" << " i_= " << x.i_ << std::endl;
        i_ = x.i_;
    }
    A(const A&& x)noexcept {
        std::cout << "ptr: [" << this << " ]" << " move ctor" << " i_= " << x.i_ << std::endl;
        i_ = x.i_;
    }
    ~A() {
        std::cout << "ptr: [" << this << " ]" << " dector" << " i_= " << i_ << std::endl;
    }
private:
    int i_;
};

int main() {
    std::vector<A> y;
    //預(yù)留10的空間
    y.reserve(10);
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(std::move(A(1)));
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(std::move(A(2)));
    std::cout << "y.size()= " << y.size() << std::endl;
    y.push_back(std::move(A(3)));
    std::cout << "y.size()= " << y.size() << std::endl;
    return 0;
};

輸出結(jié)果如下旺入,少了很多多余的操作茵瘾。

y.size()= 0
ptr: [000000954C4FF614 ] default ctor i_= 1
ptr: [00000291C41050A0 ] move ctor i_= 1
ptr: [000000954C4FF614 ] dector i_= 1
y.size()= 1
ptr: [000000954C4FF618 ] default ctor i_= 2
ptr: [00000291C41050A4 ] move ctor i_= 2
ptr: [000000954C4FF618 ] dector i_= 2
y.size()= 2
ptr: [000000954C4FF61C ] default ctor i_= 3
ptr: [00000291C41050A8 ] move ctor i_= 3
ptr: [000000954C4FF61C ] dector i_= 3
y.size()= 3
ptr: [00000291C41050A0 ] dector i_= 1
ptr: [00000291C41050A4 ] dector i_= 2
ptr: [00000291C41050A8 ] dector i_= 3
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子餐禁,更是在濱河造成了極大的恐慌,老刑警劉巖末盔,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件版仔,死亡現(xiàn)場離奇詭異益缎,居然都是意外死亡莺奔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門滑燃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來表窘,“玉大人瘤袖,你說我怎么就攤上這事艾扮∨葑欤” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長建椰。 經(jīng)常有香客問我蛛枚,道長蹦浦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任宇色,我火速辦了婚禮例隆,結(jié)果婚禮上皿曲,老公的妹妹穿的比我還像新娘坞古。我一直安慰自己,他們只是感情好绸贡,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布盯蝴。 她就那樣靜靜地躺著毅哗,像睡著了一般听怕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虑绵,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天尿瞭,我揣著相機與錄音,去河邊找鬼翅睛。 笑死声搁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捕发。 我是一名探鬼主播疏旨,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扎酷!你這毒婦竟也來了檐涝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤法挨,失蹤者是張志新(化名)和其女友劉穎谁榜,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凡纳,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡窃植,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了荐糜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巷怜。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖暴氏,靈堂內(nèi)的尸體忽然破棺而出丛版,到底是詐尸還是另有隱情,我是刑警寧澤偏序,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布页畦,位于F島的核電站,受9級特大地震影響研儒,放射性物質(zhì)發(fā)生泄漏豫缨。R本人自食惡果不足惜独令,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望好芭。 院中可真熱鬧燃箭,春花似錦、人聲如沸舍败。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽邻薯。三九已至裙戏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厕诡,已是汗流浹背累榜。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留灵嫌,地道東北人壹罚。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像寿羞,于是被迫代替她去往敵國和親猖凛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 原完整教程鏈接:6.16 An introduction to std::vector In the previo...
    Closears閱讀 502評論 0 0
  • 文檔聲明:以下資料均屬于本人在學(xué)習(xí)過程中產(chǎn)出的學(xué)習(xí)筆記绪穆,如果錯誤或者遺漏之處辨泳,請多多指正。并且該文檔在后期會隨著學(xué)...
    Aliven888閱讀 109評論 1 1
  • 基礎(chǔ)篇NumPy的主要對象是同種元素的多維數(shù)組霞幅。這是一個所有的元素都是一種類型漠吻、通過一個正整數(shù)元組索引的元素表格(...
    oyan99閱讀 5,120評論 0 18
  • 本文轉(zhuǎn)自:https://www.cnblogs.com/lancidie/archive/2011/08/05/...
    Nrocinu閱讀 1,331評論 0 1
  • Hi!這里是山幺幺的c++ primer系列司恳。寫這個系列的初衷是途乃,雖然在學(xué)校學(xué)習(xí)了c++,但總覺得對這門語言了解不...
    山幺幺閱讀 741評論 0 0