C++中4種管理數(shù)據(jù)內(nèi)存的方式總結(jié)
根據(jù)用于分配內(nèi)存的方法,C++中有3中管理數(shù)據(jù)內(nèi)存的方式:自動(dòng)存儲(chǔ)、靜態(tài)存儲(chǔ)和動(dòng)態(tài)存儲(chǔ)(有時(shí)也叫做自由存儲(chǔ)空間或堆)。在存在時(shí)間的長(zhǎng)短方面,以這三種方式分配的數(shù)據(jù)對(duì)象各不相同。下面簡(jiǎn)要介紹這三種類型。
注:C++11中新增了第四種類型——線程存儲(chǔ)
C++的4種管理數(shù)據(jù)內(nèi)存的方式
自動(dòng)存儲(chǔ)
在函數(shù)內(nèi)部定義的常規(guī)變量使用自動(dòng)存儲(chǔ)空間,被稱為自動(dòng)變量(automatic variable),這意味著它們?cè)谒鶎俚暮瘮?shù)被調(diào)用時(shí)自動(dòng)產(chǎn)生,在該函數(shù)結(jié)束時(shí)消亡。例如,當(dāng)在一個(gè)自定義的函數(shù)getname()中定義了一個(gè)temp數(shù)組時(shí),temp數(shù)組僅當(dāng)getname()函數(shù)活動(dòng)時(shí)存在。當(dāng)成許控制權(quán)回到main()時(shí),temp使用的內(nèi)存將自動(dòng)被釋放。如果getname()返回temp的地址,則main()中的name指針指向的內(nèi)存將很快得到重新使用。這就是在getname()中使用new的原因之一。
實(shí)際上,自動(dòng)變量是一個(gè)局部變量,其作用域?yàn)榘拇a塊。代碼塊是被包含在花括號(hào)中的一段代碼。
自動(dòng)變量通常存儲(chǔ)在棧中。這意味著執(zhí)行代碼塊時(shí),其中的變量將依次加入到棧中,而在離開代碼塊時(shí),將按相反的順序釋放著些變量,著被稱為后進(jìn)先出(LIFO)。因此,在程序執(zhí)行過(guò)程中,棧將不斷地增大和縮小。
靜態(tài)存儲(chǔ)
靜態(tài)存儲(chǔ)是整個(gè)程序執(zhí)行期間都存在的存儲(chǔ)方式。是變量稱為靜態(tài)的方式有兩種:一種是在函數(shù)外面定義它;另一種是在聲明變量時(shí)使用關(guān)鍵字statis:
static double fee = 56.50;
在K&R C中,只能初始化靜態(tài)數(shù)組和靜態(tài)結(jié)構(gòu),而C++ Release2.0(及后續(xù)版本)和ASNI C中,也可以初始化自動(dòng)數(shù)組和自動(dòng)結(jié)構(gòu)。
注:自動(dòng)存儲(chǔ)和靜態(tài)存儲(chǔ)關(guān)鍵在于:這些方法嚴(yán)格地限制了變量的壽命。變量可能存在于程序的整個(gè)生命周期(靜態(tài)變量),也可能只是在特定函數(shù)被執(zhí)行時(shí)存在(自動(dòng)變量)。
動(dòng)態(tài)存儲(chǔ)
new和delete運(yùn)算符提供了一種比自動(dòng)變量和靜態(tài)變量更靈活的方法。它們管理了一個(gè)內(nèi)存池,這在C++中被稱為自由存儲(chǔ)空間(free store)或堆(heap)。該內(nèi)存池同用于靜態(tài)變量和自動(dòng)變量的內(nèi)存是分開的。new和delete讓您能夠在一個(gè)函數(shù)中分配內(nèi)存,而在另一個(gè)函數(shù)中釋放它。因此,數(shù)據(jù)的聲明周期不完全收程序或函數(shù)的生命時(shí)間控制。與使用常規(guī)變量相比,使用new和delete讓程序員對(duì)程序如何使用內(nèi)存有更大的控制權(quán)。然而,內(nèi)存管理也更復(fù)雜了。在棧中,自動(dòng)添加和刪除機(jī)制使得占用的內(nèi)存總是連續(xù)的,單new和delete的相互影響可能導(dǎo)致占用的自由存儲(chǔ)區(qū)不連續(xù),這使得跟蹤新分配內(nèi)存的位置更困難。
線程存儲(chǔ)
在多線程程序中,所有線程共享程序中的變量。Linux有一全局變量,所有線程都可以使用它,改變它的值。如果每個(gè)線程希望能單獨(dú)擁有它,那么就需要使用線程存儲(chǔ)了。表面上看起來(lái)這是一個(gè)全局變量,所有線程都可以使用它,但它的值在每一個(gè)線程中又是單獨(dú)存儲(chǔ)的。
線程存儲(chǔ)的具體用法:
1.創(chuàng)建一個(gè)類型為pthread_key_t類型的變量。
2.調(diào)用pthread_key_create()來(lái)創(chuàng)建該變量,該函數(shù)有兩個(gè)參數(shù),第一個(gè)參數(shù)就是上面聲明的 pthread_key_t變量,第二個(gè)參數(shù)是一個(gè)清理函數(shù),用來(lái)在線程釋放該線程存儲(chǔ)的時(shí)候被調(diào)用,該函數(shù)指針可以設(shè)成NULL,這樣系統(tǒng)將調(diào)用默認(rèn)的清理函數(shù);
3.當(dāng)線程中需要存儲(chǔ)特殊值的時(shí)候,可以調(diào)用pthread_setspcific(),該函數(shù)有兩個(gè)參數(shù),第一個(gè)為前面聲明的pthread_key_t變量,第二個(gè)為void*變量,這樣可以存儲(chǔ)任何類型的值;
4.如果需要取出所存儲(chǔ)的值,調(diào)用pthread_getspecific(),該函數(shù)的參數(shù)為前面提到的 pthread_key_t變量,該函數(shù)返回void*類型的值;
5.注銷使用pthread_key_delete()函數(shù),該函數(shù)并不檢查當(dāng)前是否有線程正在使用,也不會(huì)調(diào)用清理函數(shù),而只是釋放以供下一次調(diào)用pthread_key_create()使用。
下面是前面提到的函數(shù)原型:
int pthread_setspecific(pthread_key_t key, const void *value); void* pthread_getspecific(pthread_key_t key); int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); int pthread_key_delete(pthread_key_t *key);
線程存儲(chǔ)例子:
#include <pthread.h> #include <stdio.h> static pthread_key_t thread_key; void* thread_function(void* args) { pthread_t spid = pthread_self(); pthread_setspecific(thread_key, (void *)spid); pthread_t gpid = (pthread_t)pthread_getspecific(thread_key); printf("set: %lu, get: %lu, %s\n", spid, gpid, (spid == gpid ? "equal":"not equal")); return NULL; } int main(int argc, char** argv) { int i; pthread_t threads[5]; pthread_key_create(&thread_key, NULL); for (i = 0; i < 5; ++i) { pthread_create(&(threads[i]), NULL, thread_function, NULL); } for (i = 0; i < 5; ++i) { pthread_join(threads[i], NULL); } pthread_key_delete(thread_key); return 0; }
棧、堆、內(nèi)存泄漏
如果使用new在自由存儲(chǔ)空間(或堆)上創(chuàng)建變量后,沒(méi)有調(diào)用delete。會(huì)發(fā)生什么?
即使包含指針的內(nèi)存由于作用域規(guī)則和對(duì)象生命周期的原因而被釋放,在自由存儲(chǔ)空間上動(dòng)態(tài)分配的變量或結(jié)構(gòu)依然存在。
實(shí)際上將會(huì)無(wú)法訪問(wèn)自由存儲(chǔ)空間的結(jié)構(gòu),因?yàn)橹赶蜻@些內(nèi)存的指針無(wú)效。
這將導(dǎo)致內(nèi)存泄露,被泄漏的內(nèi)存在程序的整個(gè)生命周期將不可使用,這些內(nèi)存被分配,但無(wú)法被使用。
到此這篇關(guān)于C++中4種管理數(shù)據(jù)內(nèi)存的方式總結(jié)的文章就介紹到這了,更多相關(guān)C++數(shù)據(jù)內(nèi)存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 操作系統(tǒng)內(nèi)存分配算法的實(shí)現(xiàn)詳解
本文主要介紹了在動(dòng)態(tài)分區(qū)管理方式下采用不同的分配算法實(shí)現(xiàn)主存分配和實(shí)現(xiàn)主存回收,旨在幫助學(xué)生理解在動(dòng)態(tài)分區(qū)管理方式下應(yīng)怎樣實(shí)現(xiàn)主存空間的分配和回收。感興趣的可以了解一下2021-11-11C語(yǔ)言實(shí)現(xiàn)猜數(shù)字小項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)實(shí)現(xiàn)猜數(shù)字小項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01C++實(shí)現(xiàn)LeetCode165.版本比較)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode165.版本比較),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01C++小知識(shí):復(fù)制粘貼代碼千萬(wàn)要小心
今天小編就為大家分享一篇關(guān)于C++小知識(shí):復(fù)制粘貼代碼千萬(wàn)要小心,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01C++虛函數(shù)表與類的內(nèi)存分布深入分析理解
對(duì)C++ 了解的人都應(yīng)該知道虛函數(shù)(Virtual Function)是通過(guò)一張?zhí)摵瘮?shù)表(Virtual Table)來(lái)實(shí)現(xiàn)的。簡(jiǎn)稱為V-Table。本文就將詳細(xì)講講虛函數(shù)表的原理與使用,需要的可以參考一下2022-08-08