C++性能優(yōu)化之一:合理使用內(nèi)存

要想在編碼過程中柄驻,寫出高效的代碼,是需要自己長期的總結(jié)和不斷學(xué)習(xí)的作谚。工作以來三娩,我自己也總結(jié)了一些小技巧,可以讓你的程序運行的更快妹懒、內(nèi)存空間使用更合理雀监,同時我還會不斷地補充該blog,爭取建立出一個屬于自己的c++ effective系列眨唬。

不多說会前,直接進入正題,以下都是我再編程過程中单绑,總結(jié)出來c++高效編碼規(guī)則回官,每個topic對應(yīng)一個規(guī)則。

局部變量合理使用

讓我們先看一段代碼:

for (int i = 0; i < 1000; ++i)
{
    string str = "do some thing:" + int2str(i);
    func(str);
}

這段代碼搂橙,在循環(huán)中使用局部變量拼裝函數(shù)func的入?yún)⑶柑幔诿看窝h(huán)過程中,str對象都會執(zhí)行一次構(gòu)造函數(shù)和析構(gòu)函數(shù)区转,那么苔巨,在這個for循環(huán)中,單單是str的組裝就耗費了1000次的內(nèi)存申請和釋放废离,局部變量占用內(nèi)存小的話侄泽,影響不會很大,如果動輒幾十蜻韭、幾百kb悼尾,那就會造成系統(tǒng)內(nèi)存使用的波動,那么是不是有更高效的方法肖方?

其實只需要把str變量放到for循環(huán)外部聲明即可闺魏,如下面代碼:

string str;
for (int i = 0; i < 1000; ++i)
{
    str = "do some thing:" + int2str(i);
    func(str);
}

這段代碼會大大降低內(nèi)存的申請和釋放次數(shù),因為首次循環(huán)后俯画,str會申請15個字節(jié)的內(nèi)存空間來容納現(xiàn)有數(shù)據(jù)析桥,第二次循環(huán)時,在賦值運算符函數(shù)中艰垂,由于str當(dāng)前空間已經(jīng)足夠容納第二次循環(huán)的數(shù)據(jù)泡仗,因此我們可以考慮對原有str內(nèi)存進行復(fù)用,所以只存在一次數(shù)據(jù)拷貝猜憎,不存在新的內(nèi)存申請和釋放娩怎;到第十次循環(huán)時,需要16個字節(jié)才能容納現(xiàn)有數(shù)據(jù)胰柑,因此需要釋放str原有內(nèi)存峦树,申請新的內(nèi)存辣辫。以此類推,我們可以算出1000次循環(huán)過程中魁巩,只有三次內(nèi)存申請和釋放,大大降低了內(nèi)存的申請和釋放次數(shù)姐浮。

小結(jié):在循環(huán)體中谷遂,局部變量如果占用內(nèi)存空間較大,會造成內(nèi)存使用不合理卖鲤,可以考慮放到循環(huán)體外聲明肾扰。

左值引用的合理使用

左值引用提升程序性能的應(yīng)用場景。
首先是函數(shù)入?yún)⒌坝猓聪旅鎯蓚€函數(shù)的聲明集晚,func1會存在一次str副本的拷貝構(gòu)造的過程,且退出函數(shù)體区匣,還需要釋放str偷拔,而func2直接將str的地址傳入函數(shù)體內(nèi)部,不存在拷貝構(gòu)造亏钩,如果str內(nèi)存很大莲绰,那么節(jié)約一次拷貝的收益還是很可觀的。

void func1(const string str);  //存在冗余拷貝構(gòu)造和析構(gòu)
void func2(const string& str); //直接傳遞str變量的地址

其次是循環(huán)體中姑丑,獲取數(shù)組元素時蛤签,如果我們不需要修改原始值,那么應(yīng)該是使用常引用直接指向數(shù)組元素的地址栅哀,避免局部變量的冗余的拷貝構(gòu)造和析構(gòu)

for (int i = 0; i < arrstrs.size(); ++i)
{
    string str = arrstrs[i];        //存在冗余拷貝構(gòu)造和析構(gòu)
    const string& str = arrstrs[i]; //直接使用arrstrs[i]變量的地址
    ...
}

動態(tài)數(shù)組容量提前設(shè)定

分層架構(gòu)的代碼中震肮,經(jīng)常出現(xiàn)需要對不同層次數(shù)據(jù)規(guī)格進行轉(zhuǎn)換,即把其他層次的數(shù)據(jù)轉(zhuǎn)化為所在層的數(shù)據(jù)格式留拾,以下是項目中經(jīng)炒辽危看見的一段代碼,主要目的是把第二層的數(shù)據(jù)轉(zhuǎn)化到第一層坐標(biāo)數(shù)據(jù)中间驮,代碼如下:

//變量格式聲明
typedef struct _FirstLayer_PosData_t
{
    double x;
    double y;
}FirstLayer_PosData_t;
typedef struct _SecondLayer_PosData_t
{
    double x;
    double y;
    int    tag;
}SecondLayer_PosData_t;
vector<FirstLayer_PosData_t> arrfir;
vector<SecondLayer_PosData_t> arrsec;
//層數(shù)據(jù)轉(zhuǎn)化代碼
for (int i = 0; i < arrsec.size(); ++i)
{
    FirstLayer_PosData_t stFirstLayerPos;
    stFirstLayerPos.x = arrsec[i].x;
    stFirstLayerPos.y = arrsec[i].y;
    arrfir.push_back(stFirstLayerPos);
}

這段代碼可以這樣改進躬厌,其實我們要拷貝的元素個數(shù)是已知的,因此我們可以直接將arrfirst數(shù)組大小設(shè)置為arrsecond的大小即可竞帽,這就避免了在循環(huán)體中動態(tài)的去擴容(每次擴容的成本是先申請新的內(nèi)存空間扛施,將舊內(nèi)存空間數(shù)據(jù)拷貝到新內(nèi)存空間,然后釋放舊內(nèi)存空間)屹篓,改進代碼如下:

arrfir.setsize(arrsec.size());
for (int i = 0; i < arrfir.size(); ++i)
{
    FirstLayer_PosData_t stFirstLayerPos;
    stFirstLayerPos.x = arrsec[i].x;
    stFirstLayerPos.y = arrsec[i].y;
    arrfir[i] = stFirstLayerPos;
}

仔細(xì)觀察下疙渣,其實還有優(yōu)化空間,局部變量是可以避免的堆巧,直接使用引用代替第一層數(shù)組的每個元素即可妄荔,最終優(yōu)化代碼如下:

arrfir.setsize(arrsecond.size());
for (int i = 0; i < arrfirst.size(); ++i)
{
    FirstLayer_PosData_t& stFirstLayerPos = arrfir[i];
    stFirstLayerPos.x = arrsec[i].x;
    stFirstLayerPos.y = arrsec[i].y;
}

move語義的合理使用

TODO

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泼菌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子啦租,更是在濱河造成了極大的恐慌哗伯,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篷角,死亡現(xiàn)場離奇詭異焊刹,居然都是意外死亡,警方通過查閱死者的電腦和手機恳蹲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門虐块,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嘉蕾,你說我怎么就攤上這事贺奠。” “怎么了错忱?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵儡率,是天一觀的道長。 經(jīng)常有香客問我航背,道長喉悴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任玖媚,我火速辦了婚禮箕肃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘今魔。我一直安慰自己勺像,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布错森。 她就那樣靜靜地躺著吟宦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涩维。 梳的紋絲不亂的頭發(fā)上殃姓,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音瓦阐,去河邊找鬼蜗侈。 笑死,一個胖子當(dāng)著我的面吹牛睡蟋,可吹牛的內(nèi)容都是我干的踏幻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼戳杀,長吁一口氣:“原來是場噩夢啊……” “哼该面!你這毒婦竟也來了夭苗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤隔缀,失蹤者是張志新(化名)和其女友劉穎题造,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猾瘸,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡晌梨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了须妻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡泛领,死狀恐怖荒吏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情渊鞋,我是刑警寧澤绰更,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站锡宋,受9級特大地震影響儡湾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜执俩,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一徐钠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧役首,春花似錦尝丐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矮固,卻和暖如春失息,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背档址。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工盹兢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辰晕。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓蛤迎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親含友。 傳聞我的和親對象是個殘疾皇子替裆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,089評論 1 32
  • 1.設(shè)計模式是什么辆童? 你知道哪些設(shè)計模式宜咒,并簡要敘述?設(shè)計模式是一種編碼經(jīng)驗把鉴,就是用比較成熟的邏輯去處理某一種類型...
    龍飝閱讀 2,138評論 0 12
  • 最全的iOS面試題及答案 iOS面試小貼士 ———————————————回答好下面的足夠了-----------...
    zweic閱讀 2,689評論 0 73
  • 每個人都是因為偶然和幸運而生故黑,或是星星,或是花草庭砍,或是泥石场晶,或是風(fēng)雨,各自都有自己所屬的星空怠缸。如果你是一朵花诗轻,閃亮...
    總督島秦觀閱讀 174評論 2 1
  • 六年前的今天,差不多也是這個時間揭北,我們奔赴在人生第一次與彼此見面的路上扳炬; 兩年前的今天,我們領(lǐng)證了搔体; 一年前的今天...
    茶顏閱讀 244評論 0 0