淺談C++內(nèi)存分配及變長(zhǎng)數(shù)組的動(dòng)態(tài)分配
第一部分 C++內(nèi)存分配
一。關(guān)于內(nèi)存
1、內(nèi)存分配方式
內(nèi)存分配方式有三種:
(1)從靜態(tài)存儲(chǔ)區(qū)域分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在
例如全局變量,static變量。
(2)在棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存
儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。
(3) 從堆上分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc或new申請(qǐng)任意多少的內(nèi)存,程序員自
己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由我們決定,使用非常靈活,但問題也最多。
2.內(nèi)存使用錯(cuò)誤
發(fā)生內(nèi)存錯(cuò)誤是件非常麻煩的事情。編譯器不能自動(dòng)發(fā)現(xiàn)這些錯(cuò)誤,通常是在程序運(yùn)行時(shí)才能捕捉到。
而這些錯(cuò)誤大多沒有明顯的癥狀,時(shí)隱時(shí)現(xiàn),增加了改錯(cuò)的難度。有時(shí)用戶怒氣沖沖地把你找來,程序卻沒有
發(fā)生任何問題,你一走,錯(cuò)誤又發(fā)作了。 常見的內(nèi)存錯(cuò)誤及其對(duì)策如下:
* 內(nèi)存分配未成功,卻使用了它。
編程新手常犯這種錯(cuò)誤,因?yàn)樗麄儧]有意識(shí)到內(nèi)存分配會(huì)不成功。常用解決辦法是,在使用內(nèi)存之前檢查
指針是否為NULL。如果是用malloc或new來申請(qǐng)內(nèi)存,應(yīng)該用if(p==NULL) 或if(p!=NULL)進(jìn)行防錯(cuò)處理。
* 內(nèi)存分配雖然成功,但是尚未初始化就引用它。
犯這種錯(cuò)誤主要有兩個(gè)起因:一是沒有初始化的觀念;二是誤以為內(nèi)存的缺省初值全為零,導(dǎo)致引用初值
錯(cuò)誤(例如數(shù)組)。 內(nèi)存的缺省初值究竟是什么并沒有統(tǒng)一的標(biāo)準(zhǔn),盡管有些時(shí)候?yàn)榱阒?,我們寧可信其無不
可信其有。所以無論用何種方式創(chuàng)建數(shù)組,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。
* 內(nèi)存分配成功并且已經(jīng)初始化,但操作越過了內(nèi)存的邊界。
例如在使用數(shù)組時(shí)經(jīng)常發(fā)生下標(biāo)“多1”或者“少1”的操作。特別是在for循環(huán)語句中,循環(huán)次數(shù)很容易搞錯(cuò),導(dǎo)致數(shù)組操作越界。
* 忘記了釋放內(nèi)存,造成內(nèi)存泄露。
含有這種錯(cuò)誤的函數(shù)每被調(diào)用一次就丟失一塊內(nèi)存。剛開始時(shí)系統(tǒng)的內(nèi)存充足,你看不到錯(cuò)誤。終有一次
程序突然死掉,系統(tǒng)出現(xiàn)提示:內(nèi)存耗盡。
動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),程序中malloc與free的使用次數(shù)一定要相同,否則肯定有錯(cuò)誤
(new/delete同理)。
* 釋放了內(nèi)存卻繼續(xù)使用它。
有三種情況:
(1)程序中的對(duì)象調(diào)用關(guān)系過于復(fù)雜,實(shí)在難以搞清楚某個(gè)對(duì)象究竟是否已經(jīng)釋放了內(nèi)存,此時(shí)應(yīng)該重新
設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),從根本上解決對(duì)象管理的混亂局面。
(2)函數(shù)的return語句寫錯(cuò)了,注意不要返回指向“棧內(nèi)存”的“指針”或者“引用”,因?yàn)樵搩?nèi)存在函
數(shù)體結(jié)束時(shí)被自動(dòng)銷毀。
(3)使用free或delete釋放了內(nèi)存后,沒有將指針設(shè)置為NULL。導(dǎo)致產(chǎn)生“野指針”。
【規(guī)則1】用malloc或new申請(qǐng)內(nèi)存之后,應(yīng)該立即檢查指針值是否為NULL。防止使用指針值為NULL的內(nèi)存
【規(guī)則2】不要忘記為數(shù)組和動(dòng)態(tài)內(nèi)存賦初值。防止將未被初始化的內(nèi)存作為右值使用。
【規(guī)則3】避免數(shù)組或指針的下標(biāo)越界,特別要當(dāng)心發(fā)生“多1”或者“少1”操作。
【規(guī)則4】動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),防止內(nèi)存泄漏。
【規(guī)則5】用free或delete釋放了內(nèi)存之后,立即將指針設(shè)置為NULL,防止產(chǎn)生“野指針”。
二. 詳解new,malloc,GlobalAlloc
1. new
new和delete運(yùn)算符用于動(dòng)態(tài)分配和撤銷內(nèi)存的運(yùn)算符
new用法:
1> 開辟單變量地址空間
1)new int; //開辟一個(gè)存放數(shù)組的存儲(chǔ)空間,返回一個(gè)指向該存儲(chǔ)空間的地址.int *a = new
int 即為將一個(gè)int類型的地址賦值給整型指針a.
2)int *a = new int(5) 作用同上,但是同時(shí)將整數(shù)賦值為5
2> 開辟數(shù)組空間
一維: int *a = new int[100];開辟一個(gè)大小為100的整型數(shù)組空間
一般用法: new 類型 [初值]
delete用法:
1> int *a = new int;
delete a; //釋放單個(gè)int的空間
2>int *a = new int[5];
delete [] a; //釋放int數(shù)組空間
要訪問new所開辟的結(jié)構(gòu)體空間,無法直接通過變量名進(jìn)行,只能通過賦值的指針進(jìn)行訪問.
用new和delete可以動(dòng)態(tài)開辟,撤銷地址空間.在編程序時(shí),若用完一個(gè)變量(一般是暫時(shí)存儲(chǔ)的數(shù)組),
下次需要再用,但卻又想省去重新初始化的功夫,可以在每次開始使用時(shí)開辟一個(gè)空間,在用完后撤銷它.
2. malloc
原型:extern void *malloc(unsigned int num_bytes);
用法:#i nclude <malloc.h>或#i nclude <stdlib.h>
功能:分配長(zhǎng)度為num_bytes字節(jié)的內(nèi)存塊
說明:如果分配成功則返回指向被分配內(nèi)存的指針,否則返回空指針NULL。
當(dāng)內(nèi)存不再使用時(shí),應(yīng)使用free()函數(shù)將內(nèi)存塊釋放。
malloc的語法是:指針名=(數(shù)據(jù)類型*)malloc(長(zhǎng)度),(數(shù)據(jù)類型*)表示指針.
說明:malloc 向系統(tǒng)申請(qǐng)分配指定size個(gè)字節(jié)的內(nèi)存空間。返回類型是 void* 類型。void* 表示未確定類型
的指針。C,C++規(guī)定,void* 類型可以強(qiáng)制轉(zhuǎn)換為任何其它類型的指針。
malloc()函數(shù)的工作機(jī)制
malloc函數(shù)的實(shí)質(zhì)體現(xiàn)在,它有一個(gè)將可用的內(nèi)存塊連接為一個(gè)長(zhǎng)長(zhǎng)的列表的所謂空閑鏈表。調(diào)用malloc
函數(shù)時(shí),它沿連接表尋找一個(gè)大到足以滿足用戶請(qǐng)求所需要的內(nèi)存塊。然后,將該內(nèi)存塊一分為二(一塊的大
小與用戶請(qǐng)求的大小相等,另一塊的大小就是剩下的字節(jié))。接下來,將分配給用戶的那塊內(nèi)存?zhèn)鹘o用戶,并
將剩下的那塊(如果有的話)返回到連接表上。調(diào)用free函數(shù)時(shí),它將用戶釋放的內(nèi)存塊連接到空閑鏈上。到
最后,空閑鏈會(huì)被切成很多的小內(nèi)存片段,如果這時(shí)用戶申請(qǐng)一個(gè)大的內(nèi)存片段,那么空閑鏈上可能沒有可以
滿足用戶要求的片段了。于是,malloc函數(shù)請(qǐng)求延時(shí),并開始在空閑鏈上翻箱倒柜地檢查各內(nèi)存片段,對(duì)它們
進(jìn)行整理,將相鄰的小空閑塊合并成較大的內(nèi)存塊。
和new的不同
從函數(shù)聲明上可以看出。malloc 和 new 至少有兩個(gè)不同: new 返回指定類型的指針,并且可以自動(dòng)計(jì)算所需
要大小。比如:
int *p;
p = new int; //返回類型為int* 類型(整數(shù)型指針),分配大小為 sizeof(int);
或:
int* parr;
parr = new int [100]; //返回類型為 int* 類型(整數(shù)型指針),分配大小為 sizeof(int) * 100;
而 malloc 則必須由我們計(jì)算要字節(jié)數(shù),并且在返回后強(qiáng)行轉(zhuǎn)換為實(shí)際類型的指針。
int* p;
p = (int *) malloc (sizeof(int));
第一、malloc 函數(shù)返回的是 void * 類型,如果你寫成:p = malloc (sizeof(int)); 則程序無法通過編譯,
報(bào)錯(cuò):“不能將 void* 賦值給 int * 類型變量”。所以必須通過 (int *) 來將強(qiáng)制轉(zhuǎn)換。
第二、函數(shù)的實(shí)參為 sizeof(int) ,用于指明一個(gè)整型數(shù)據(jù)需要的大小。如果你寫成:
int* p = (int *) malloc (1);
代碼也能通過編譯,但事實(shí)上只分配了1個(gè)字節(jié)大小的內(nèi)存空間,當(dāng)你往里頭存入一個(gè)整數(shù),就會(huì)有3個(gè)字節(jié)無
家可歸,而直接“住進(jìn)鄰居家”!造成的結(jié)果是后面的內(nèi)存中原有數(shù)據(jù)內(nèi)容全部被清空。
3. GlobalAlloc
VC中關(guān)于GlobalAlloc,GlobalLock,GlobalUnLock
調(diào)用GlobalAlloc函數(shù)分配一塊內(nèi)存,該函數(shù)會(huì)返回分配的內(nèi)存句柄。
調(diào)用GlobalLock函數(shù)鎖定內(nèi)存塊,該函數(shù)接受一個(gè)內(nèi)存句柄作為參數(shù),然后返回一個(gè)指向被鎖定的內(nèi)存塊的指針。 您可以用該指針來讀寫內(nèi)存。
調(diào)用GlobalUnlock函數(shù)來解鎖先前被鎖定的內(nèi)存,該函數(shù)使得指向內(nèi)存塊的指針無效。
調(diào)用GlobalFree函數(shù)來釋放內(nèi)存塊。您必須傳給該函數(shù)一個(gè)內(nèi)存句柄。
GlobalAlloc
說明
分配一個(gè)全局內(nèi)存塊
返回值
Long,返回全局內(nèi)存句柄。零表示失敗。會(huì)設(shè)置GetLastError
參數(shù)表
參數(shù) 類型及說明
wFlags Long,對(duì)分配的內(nèi)存類型進(jìn)行定義的常數(shù)標(biāo)志,如下所示:
GMEM_FIXED 分配一個(gè)固定內(nèi)存塊
GMEM_MOVEABLE 分配一個(gè)可移動(dòng)內(nèi)存塊
GMEM_DISCARDABLE 分配一個(gè)可丟棄內(nèi)存塊
GMEM_NOCOMPACT 堆在這個(gè)函數(shù)調(diào)用期間不進(jìn)行累積
GMEM_NODISCARD 函數(shù)調(diào)用期間不丟棄任何內(nèi)存塊
GMEM_ZEROINIT 新分配的內(nèi)存塊全部初始化成零
dwBytes Long,要分配的字符數(shù)
GlobalLock
函數(shù)功能描述:鎖定一個(gè)全局的內(nèi)存對(duì)象,返回指向該對(duì)象的第一個(gè)字節(jié)的指針
函數(shù)原型:
LPVOID GlobalLock( HGLOBAL hMem )
參數(shù):
hMem:全局內(nèi)存對(duì)象的句柄。這個(gè)句柄是通過GlobalAlloc或GlobalReAlloc來得到的
返回值:
調(diào)用成功,返回指向該對(duì)象的第一個(gè)字節(jié)的指針
調(diào)用失敗,返回NULL,可以用GetLastError來獲得出錯(cuò)信息
注意:
調(diào)用過GlobalLock鎖定一塊內(nèi)存區(qū)后,一定要調(diào)用GlobalUnlock來解鎖
GlobalUnlock
函數(shù)功能描述:解除被鎖定的全局內(nèi)存對(duì)象
函數(shù)原型:BOOL GlobalUnlock( HGLOBAL hMem );
參數(shù):hMem:全局內(nèi)存對(duì)象的句柄
返回值:
非零值,指定的內(nèi)存對(duì)象仍處于被鎖定狀態(tài)0,函數(shù)執(zhí)行出錯(cuò),可以用GetLastError來獲得出錯(cuò)信息,如果返回NO_ERROR,則表示內(nèi)存對(duì)象已經(jīng)解鎖了
注意:這個(gè)函數(shù)實(shí)際上是將內(nèi)存對(duì)象的鎖定計(jì)數(shù)器減一,如果計(jì)數(shù)器不為0,則表示執(zhí)行過多個(gè)GlobalLock
函數(shù)來對(duì)這個(gè)內(nèi)存對(duì)象加鎖,需要對(duì)應(yīng)數(shù)目的GlobalUnlock函數(shù)來解鎖。如果通過GetLastError函數(shù)返回錯(cuò)誤
碼為ERROR_NOT_LOCKED,則表示未加鎖或已經(jīng)解鎖。
示例:
// Malloc memory hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, nSize); // Lock memory pMem = (BYTE *) GlobalLock(hMem); .................. // Unlock memory GlobalUnlock(hMem); GlobalFree(hMem);
三 總結(jié)
靈活自由是C/C++語言的一大特色,而這也為C/C++程序員出了一個(gè)難題。當(dāng)程序越來越復(fù)雜時(shí),內(nèi)存的管理也會(huì)變得越加復(fù)雜,稍有不慎就會(huì)出現(xiàn)內(nèi)存問 題。內(nèi)存泄漏是最常見的內(nèi)存問題之一。內(nèi)存泄漏如果不是很嚴(yán)重,在短時(shí)間內(nèi)對(duì)程序不會(huì)有太大的影響,這也使得內(nèi)存泄漏問題有很強(qiáng)的隱蔽性,不容易被發(fā)現(xiàn)。 然而不管內(nèi)
存泄漏多么輕微,當(dāng)程序長(zhǎng)時(shí)間運(yùn)行時(shí),其破壞力是驚人的,從性能下降到內(nèi)存耗盡,甚至?xí)绊懙狡渌绦虻恼_\(yùn)行。另外內(nèi)存問題的一個(gè)共同特點(diǎn) 是,內(nèi)存問題本身并不會(huì)有很明顯的現(xiàn)象,當(dāng)有異?,F(xiàn)象出現(xiàn)時(shí)已時(shí)過境遷,其現(xiàn)場(chǎng)已非出現(xiàn)問題時(shí)的現(xiàn)場(chǎng)了,這給調(diào)試內(nèi)存問題帶來了很大的難度。
下載Windows Debug 工具, http://www.microsoft.com/whdc/devtools/debugging/default.mspx
安裝后,使用其中的gflags.exe工具打開PageHeap,
gflags -p /enable MainD.exe /full
重新使用VS用調(diào)試方式運(yùn)行,很快就找到了出錯(cuò)位置,因?yàn)樵谀硞€(gè)靜態(tài)函數(shù)中筆誤導(dǎo)致
在編寫穩(wěn)定的服務(wù)器程序時(shí),這個(gè)工具尤為有用。
第二部分 數(shù)組的動(dòng)態(tài)分配及實(shí)例
一、動(dòng)態(tài)分配二維數(shù)組的一般方法是這樣:假設(shè)數(shù)組存的數(shù)據(jù)類型是int
int **p=NULL; p=new int*[nWidth]; if (!p){ return NULL; } for (int j=0;j<nWidth;j++){ p[j]=new int[nHeight]; if (!p[j]){ return NULL; } }
這段代碼淺顯易懂,先分配第1維,在循環(huán)分配第2維。假設(shè)二維數(shù)組是3×2的,每一句運(yùn)行完后的內(nèi)存情況如圖所示(方格表示內(nèi)存,xx表示隨機(jī)數(shù)。下面是內(nèi)存地址。當(dāng)然,這個(gè)地址是個(gè)示意,事實(shí)不會(huì)分配到那的。):
第一句完后分配了3個(gè)內(nèi)存單元
循環(huán)分配后,注意下面3段內(nèi)存是不連續(xù)的。這樣用下表p[n][m]操作數(shù)組沒問題,如果整塊內(nèi)存操作就會(huì)有問題了。
原意是想把下面的3塊6個(gè)內(nèi)存單元清0,可是事與愿違,把從p開始后面6個(gè)內(nèi)存單元清0了,p[]不能用了。p后面只有3個(gè)已分配的內(nèi)存單元,卻要操作6個(gè),另外3個(gè)是未知區(qū)域。清了后面虛線的3塊未知區(qū)域,這就很危險(xiǎn)了,可能導(dǎo)致程序崩潰。
這樣分配的內(nèi)存需要循環(huán)釋放。
對(duì)這個(gè)方法有一改進(jìn),如下:
int **p=NULL; p=new int *[nWidth]; if (!p){ return NULL; } p[0]=new int[nWidth*nHeight]; if (!p[0]){ delete[] p; return NULL; } ZeroMemory(p[0],nWidth*nHeight*sizeof(int)); for (int i=1;i<nWidth;i++){ p[i]=p[i-1]+nHeight; }
這段代碼解決了分配的空間不連續(xù)的問題。每一句運(yùn)行完后的內(nèi)存情況如圖所示:
第一句和上面一樣。
這6個(gè)內(nèi)存單元是一次分配的,所以連續(xù)。
這個(gè)二維數(shù)組的數(shù)據(jù)首地址是p[0],p是第2維的索引首地址。所以如果要對(duì)二維數(shù)組進(jìn)行整體的內(nèi)存(緩沖區(qū) buffer)操作,要以p[0]為操作對(duì)象的首地址。
到此,索引與對(duì)應(yīng)的數(shù)據(jù)地址關(guān)聯(lián)上了。這個(gè)二維數(shù)組既可以通過下表p[][]來操作,又可以操作緩沖區(qū)。操作緩沖區(qū)的函數(shù)比如memcpy,cfile的writehuge和readhuge使用起來很方便,省去了2次循環(huán)的麻煩。
至于釋放,不必循環(huán)釋放。因?yàn)閚ew了2次,所以只需delete2次就行了:
if(!p){ return; } delete []p[0]; p[0]=NULL; delete[] p; p=NULL;
二 實(shí)例
<span style="font-size:14px;">// malloc2d.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <stdlib.h> #include <string.h> using namespace std; //第一種方法,分配連續(xù)空間 void **malloc2d(int row,int col,int size) { void **arr; int indexsize=sizeof(void*)*row;//空出indexsize大小的空間用作? void*為什么不行? int totalsize=size*row*col; arr=(void**)malloc(indexsize+totalsize); if(arr!=NULL) { unsigned char *head;//博客中是void *head版本,但編譯都通過不了,改成unsigned char* 后編譯通過,但不明白運(yùn)行結(jié)果為什么不對(duì) head=(unsigned char *)arr+indexsize; memset(arr,0,indexsize+totalsize); for(int i=0;i<row;i++) arr[i]=head+size*i*col; } return arr; } void free2d(void **arr) { if(arr!=NULL) free(arr); } //第二中方法,分配連續(xù)空間,C++的實(shí)現(xiàn)版, template <typename T> T **darray_new(int row, int col) { int size=sizeof(T); void **arr=(void **) malloc(sizeof(void *) * row + size * row * col); if (arr != NULL) { unsigned char * head; head=(unsigned char *) arr + sizeof(void *) * row; for (int i=0; i<row; ++i) { arr[i]= head + size * i * col; for (int j=0; j<col; ++j) new (head + size * (i * col + j)) T;//這一句比較有意思,想一想為什么? } } return (T**) arr; } template <typename T> void darray_free(T **arr, int row, int col)//注意要一個(gè)一個(gè)delete了,蛋疼,不過對(duì)于自定義的數(shù)據(jù)類型,很有必要 { for (int i=0; i<row; ++i) for (int j=0; j<col; ++j) arr[i][j].~T();//這是什么玩意兒?!模板析構(gòu)?因?yàn)槭褂昧薾ew?所以用析構(gòu)函數(shù)的delete? if (arr != NULL) free((void **)arr); } int _tmain(int argc, _TCHAR* argv[]) { //一維數(shù)組動(dòng)態(tài)分配 //int n; //cin>>n; ////int *p=new int[n];//一維數(shù)組動(dòng)態(tài)分配方法一 //int *p=(int*)malloc(n*sizeof(int));//一維數(shù)組動(dòng)態(tài)分配方法二 //for(int i=0;i<n;i++) // cin>>p[i]; //cout<<endl; //for(int i=0;i<n;i++) // cout<<p[i]<<" "; //二維變長(zhǎng)數(shù)組的動(dòng)態(tài)分配,本人喜歡這種方法,雖然空間不連續(xù),但同樣可以進(jìn)行p[i][j]的尋址,為什么博客中特意寫上面介紹的函數(shù)來實(shí)現(xiàn)還沒找到太好的理由 //int n; //cin>>n; //int *p[2]; //p[0]=new int[n]; //p[1]=new int[n+1]; //for(int i=0;i<n;i++) // cin>>p[0][i]; //cout<<&p[0]<<" "<<&p[1]<<endl;//p[0],p[1]是連續(xù)的 //cout<<&p[0]<<" "<<&p[0][0]<<" "<<&p[0][1]<<endl;//p[0]!=p[0][0],但p[0][0],p[0][1]是連續(xù)的 ////C版本的,分配連續(xù)空間 //int**m=(int**)malloc2d(5,5,sizeof(int)); //int i,j; //for( i=0;i<5;i++) //void* 泛型指針,有待剖析 // for( j=0;j<5;j++) // m[i][j]=0; //for( i=0;i<5;i++) //{ // for( j=0;j<5;j++) // cout<<m[i][j]<<" "; // cout<<endl; //} //free2d((void**)m); int** m=darray_new<int>(5,5);//注意模板函數(shù)怎么實(shí)現(xiàn)的 <int>! int i,j; for( i=0;i<5;i++) for( j=0;j<5;j++) m[i][j]=1; for( i=0;i<5;i++) { for( j=0;j<5;j++) cout<<m[i][j]<<" "; cout<<endl; } darray_free(m,5,5); return 0; } </span>
以上這篇淺談C++內(nèi)存分配及變長(zhǎng)數(shù)組的動(dòng)態(tài)分配就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
用C++編寫擴(kuò)展node.js(node-ffi版)
今天小編就為大家分享一篇關(guān)于用C++編寫擴(kuò)展node.js(node-ffi版),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12C++實(shí)現(xiàn)簡(jiǎn)單BP神經(jīng)網(wǎng)絡(luò)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單BP神經(jīng)網(wǎng)絡(luò),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05c++實(shí)現(xiàn)跳躍表(Skip List)的方法示例
跳表(skiplist)是一個(gè)非常優(yōu)秀的數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)簡(jiǎn)單,插入、刪除、查找的復(fù)雜度均為O(logN),下面這篇文章主要介紹了c++實(shí)現(xiàn)跳躍表(Skip List)的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09C++算法學(xué)習(xí)之貪心算法的應(yīng)用
貪心算法是指,在對(duì)問題求解時(shí),總是做出在當(dāng)前看來是最好的選擇。本文為大家準(zhǔn)備了幾個(gè)示例,從而能深入了解貪心算法的應(yīng)用,需要的可以參考一下2022-05-05用C++實(shí)現(xiàn),將一句話里的單詞進(jìn)行倒置的方法詳解
本篇文章是對(duì)用C++實(shí)現(xiàn),將一句話里的單詞進(jìn)行倒置的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C語言驅(qū)動(dòng)開發(fā)之內(nèi)核解鎖與強(qiáng)刪文件
在某些時(shí)候我們的系統(tǒng)中會(huì)出現(xiàn)一些無法被正常刪除的文件,如果想要強(qiáng)制刪除則需要在驅(qū)動(dòng)層面對(duì)其進(jìn)行解鎖后才可刪掉,本文為大家介紹了內(nèi)核解鎖與強(qiáng)刪文件的方法,希望對(duì)大家有所幫助2023-06-06C++中整形與浮點(diǎn)型如何在內(nèi)存中的存儲(chǔ)詳解
大家好!這期和大家分享整形和浮點(diǎn)型是如何在數(shù)據(jù)是如何在內(nèi)存中存儲(chǔ),下面文章具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-05-05Java?C++?算法題解leetcode145商品折扣后最終價(jià)格單調(diào)棧
這篇文章主要介紹了Java?C++?算法題解leetcode145商品折扣后最終價(jià)格單調(diào)棧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Qt項(xiàng)目實(shí)戰(zhàn)之實(shí)現(xiàn)MP3音樂播放器
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)MP3音樂播放器,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以了解一下2023-03-03