C++中4種管理數(shù)據(jù)內(nèi)存的方式總結(jié)
根據(jù)用于分配內(nèi)存的方法,C++中有3中管理數(shù)據(jù)內(nèi)存的方式:自動存儲、靜態(tài)存儲和動態(tài)存儲(有時也叫做自由存儲空間或堆)。在存在時間的長短方面,以這三種方式分配的數(shù)據(jù)對象各不相同。下面簡要介紹這三種類型。
注:C++11中新增了第四種類型——線程存儲
C++的4種管理數(shù)據(jù)內(nèi)存的方式
自動存儲
在函數(shù)內(nèi)部定義的常規(guī)變量使用自動存儲空間,被稱為自動變量(automatic variable),這意味著它們在所屬的函數(shù)被調(diào)用時自動產(chǎn)生,在該函數(shù)結(jié)束時消亡。例如,當在一個自定義的函數(shù)getname()中定義了一個temp數(shù)組時,temp數(shù)組僅當getname()函數(shù)活動時存在。當成許控制權(quán)回到main()時,temp使用的內(nèi)存將自動被釋放。如果getname()返回temp的地址,則main()中的name指針指向的內(nèi)存將很快得到重新使用。這就是在getname()中使用new的原因之一。
實際上,自動變量是一個局部變量,其作用域為包含它的代碼塊。代碼塊是被包含在花括號中的一段代碼。
自動變量通常存儲在棧中。這意味著執(zhí)行代碼塊時,其中的變量將依次加入到棧中,而在離開代碼塊時,將按相反的順序釋放著些變量,著被稱為后進先出(LIFO)。因此,在程序執(zhí)行過程中,棧將不斷地增大和縮小。
靜態(tài)存儲
靜態(tài)存儲是整個程序執(zhí)行期間都存在的存儲方式。是變量稱為靜態(tài)的方式有兩種:一種是在函數(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中,也可以初始化自動數(shù)組和自動結(jié)構(gòu)。
注:自動存儲和靜態(tài)存儲關(guān)鍵在于:這些方法嚴格地限制了變量的壽命。變量可能存在于程序的整個生命周期(靜態(tài)變量),也可能只是在特定函數(shù)被執(zhí)行時存在(自動變量)。
動態(tài)存儲
new和delete運算符提供了一種比自動變量和靜態(tài)變量更靈活的方法。它們管理了一個內(nèi)存池,這在C++中被稱為自由存儲空間(free store)或堆(heap)。該內(nèi)存池同用于靜態(tài)變量和自動變量的內(nèi)存是分開的。new和delete讓您能夠在一個函數(shù)中分配內(nèi)存,而在另一個函數(shù)中釋放它。因此,數(shù)據(jù)的聲明周期不完全收程序或函數(shù)的生命時間控制。與使用常規(guī)變量相比,使用new和delete讓程序員對程序如何使用內(nèi)存有更大的控制權(quán)。然而,內(nèi)存管理也更復(fù)雜了。在棧中,自動添加和刪除機制使得占用的內(nèi)存總是連續(xù)的,單new和delete的相互影響可能導(dǎo)致占用的自由存儲區(qū)不連續(xù),這使得跟蹤新分配內(nèi)存的位置更困難。
線程存儲
在多線程程序中,所有線程共享程序中的變量。Linux有一全局變量,所有線程都可以使用它,改變它的值。如果每個線程希望能單獨擁有它,那么就需要使用線程存儲了。表面上看起來這是一個全局變量,所有線程都可以使用它,但它的值在每一個線程中又是單獨存儲的。
線程存儲的具體用法:
1.創(chuàng)建一個類型為pthread_key_t類型的變量。
2.調(diào)用pthread_key_create()來創(chuàng)建該變量,該函數(shù)有兩個參數(shù),第一個參數(shù)就是上面聲明的 pthread_key_t變量,第二個參數(shù)是一個清理函數(shù),用來在線程釋放該線程存儲的時候被調(diào)用,該函數(shù)指針可以設(shè)成NULL,這樣系統(tǒng)將調(diào)用默認的清理函數(shù);
3.當線程中需要存儲特殊值的時候,可以調(diào)用pthread_setspcific(),該函數(shù)有兩個參數(shù),第一個為前面聲明的pthread_key_t變量,第二個為void*變量,這樣可以存儲任何類型的值;
4.如果需要取出所存儲的值,調(diào)用pthread_getspecific(),該函數(shù)的參數(shù)為前面提到的 pthread_key_t變量,該函數(shù)返回void*類型的值;
5.注銷使用pthread_key_delete()函數(shù),該函數(shù)并不檢查當前是否有線程正在使用,也不會調(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);
線程存儲例子:
#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在自由存儲空間(或堆)上創(chuàng)建變量后,沒有調(diào)用delete。會發(fā)生什么?
即使包含指針的內(nèi)存由于作用域規(guī)則和對象生命周期的原因而被釋放,在自由存儲空間上動態(tài)分配的變量或結(jié)構(gòu)依然存在。
實際上將會無法訪問自由存儲空間的結(jié)構(gòu),因為指向這些內(nèi)存的指針無效。
這將導(dǎo)致內(nèi)存泄露,被泄漏的內(nèi)存在程序的整個生命周期將不可使用,這些內(nèi)存被分配,但無法被使用。
到此這篇關(guān)于C++中4種管理數(shù)據(jù)內(nèi)存的方式總結(jié)的文章就介紹到這了,更多相關(guān)C++數(shù)據(jù)內(nèi)存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 操作系統(tǒng)內(nèi)存分配算法的實現(xiàn)詳解
本文主要介紹了在動態(tài)分區(qū)管理方式下采用不同的分配算法實現(xiàn)主存分配和實現(xiàn)主存回收,旨在幫助學生理解在動態(tài)分區(qū)管理方式下應(yīng)怎樣實現(xiàn)主存空間的分配和回收。感興趣的可以了解一下2021-11-11
C++虛函數(shù)表與類的內(nèi)存分布深入分析理解
對C++ 了解的人都應(yīng)該知道虛函數(shù)(Virtual Function)是通過一張?zhí)摵瘮?shù)表(Virtual Table)來實現(xiàn)的。簡稱為V-Table。本文就將詳細講講虛函數(shù)表的原理與使用,需要的可以參考一下2022-08-08

