C++表達(dá)式new與delete知識(shí)詳解
在C++中,new表達(dá)式用于動(dòng)態(tài)創(chuàng)建對(duì)象,即在堆(自由存儲(chǔ)區(qū))空間上為對(duì)象分配內(nèi)存,而程序員也要小心的使用這些申請(qǐng)來(lái)的內(nèi)存空間,當(dāng)不再使用時(shí)應(yīng)該調(diào)用delete表達(dá)式來(lái)釋放該存儲(chǔ)空間并且將指針置零。 本文學(xué)習(xí)了如何動(dòng)態(tài)創(chuàng)建對(duì)象,動(dòng)態(tài)創(chuàng)建的對(duì)象與一般對(duì)象的區(qū)別,動(dòng)態(tài)創(chuàng)建的對(duì)象的初始化以及釋放動(dòng)態(tài)分配的內(nèi)存等知識(shí)點(diǎn)。
C++中分配的內(nèi)存大致有三類:靜態(tài)存儲(chǔ)區(qū),棧內(nèi)存和堆內(nèi)存
其中,靜態(tài)存儲(chǔ)區(qū)是在程序編譯階段就已經(jīng)分配好的,用于全局變量,static變量等;堆棧是比較常用的對(duì)象存儲(chǔ)方式。
new和delete是C++中程序員申請(qǐng)和撤銷堆內(nèi)存的唯一方式(據(jù)我所知)。
1. 創(chuàng)建對(duì)象
無(wú)論是定義內(nèi)置類型變量還是類類型變量,都必須指定其對(duì)應(yīng)的數(shù)據(jù)類型和名字。
動(dòng)態(tài)創(chuàng)建對(duì)象只需指定其數(shù)據(jù)類型,而不必為該對(duì)象命名。
也就是說(shuō),變量定義得到的對(duì)象可以通過(guò)額外定義的指針或其對(duì)象名本身來(lái)訪問(wèn),而動(dòng)態(tài)創(chuàng)建方式得到的對(duì)象只能通過(guò)返回的指針來(lái)訪問(wèn),因?yàn)樵搶?duì)象并沒(méi)有名字。
2. 初始化
a. 可以在變量定義或是動(dòng)態(tài)創(chuàng)建的階段初始化對(duì)象,例如:
int i(222); // definition, initialized int *pi = new int(222) // dynamically, initialized
b. 在這還要說(shuō)一說(shuō)變量定義時(shí)的默認(rèn)初始化問(wèn)題:
內(nèi)置類型的變量初始化與其定義位置有關(guān):函數(shù)外的自動(dòng)初始化為零,而函數(shù)內(nèi)的沒(méi)有初始化。對(duì)于類類型的變量,程序總是會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù)來(lái)初始化,這個(gè)默認(rèn)構(gòu)造函數(shù)可以是系統(tǒng)自動(dòng)生成的,也可以是程序員定義的。如果沒(méi)有默認(rèn)構(gòu)造函數(shù),那么該類型變量的定義也就不能采用默認(rèn)初始化方式,必須提供顯式的初始化式。
動(dòng)態(tài)創(chuàng)建的對(duì)象默認(rèn)初始化與函數(shù)內(nèi)變量定義的初始化方式相同,例如:
string *ps = new string; // initialized to empty string int *pi = new int; // pi points to an uninitialized int
c. 動(dòng)態(tài)創(chuàng)建對(duì)象的值初始化(value-initialize)
這種值初始化不能用于變量定義,而只能用于動(dòng)態(tài)創(chuàng)建方式。
string *ps2 = new string(); // initialized to empty string int *pi = new int(); // pi points to an int value-initialized to 0
值初始化表明程序員想要做初始化,但并未提供特定的初值。實(shí)際上,對(duì)于提供了默認(rèn)構(gòu)造函數(shù)的類類型(如string),沒(méi)有必要對(duì)其對(duì)象進(jìn)行值初始化:無(wú)論程序是明確地不初始化還是要求進(jìn)行值初始化,都會(huì)自動(dòng)調(diào)用其默認(rèn)構(gòu)造函數(shù)初始化該對(duì)象。值初始化真正有用的是對(duì)于內(nèi)置類型。另外需要注意的一點(diǎn)是,值初始化的 () 語(yǔ)法必須置于類型名后面,而不是變量名后面,否則得到的是一個(gè)函數(shù)聲明,如下:
int myValue(); // not value-initialized int variable, but a function named myValue int *myPtr = new int(); // correct! a value-initialized int object
對(duì)于沒(méi)有默認(rèn)構(gòu)造函數(shù)的類類型,無(wú)論是變量定義還是動(dòng)態(tài)創(chuàng)建對(duì)象都必須采用顯式初始化。
3. 撤銷對(duì)象
動(dòng)態(tài)創(chuàng)建的對(duì)象用完后,程序員必須顯式地將該對(duì)象占用的內(nèi)存返還給自由存儲(chǔ)區(qū)。C++提供了delete表達(dá)式釋放指針?biāo)赶虻牡刂房臻g。
delete myPtr;
上述語(yǔ)句釋放 myPtr 指向的 int 型對(duì)象所占用的內(nèi)存。
C++沒(méi)有明確定義如何釋放指向不是用 new 分配的內(nèi)存地址的指針。此外,編譯器通常不能斷定一個(gè)指針究竟指向什么類型的對(duì)象,因此如果調(diào)用delete 企圖釋放指向棧內(nèi)存地址的指針時(shí),編譯器并不會(huì)報(bào)錯(cuò),但請(qǐng)盡量不要依賴于該未定義的行為。
在C++中 delete 一個(gè)零值指針是合法且安全的,但實(shí)際上毫無(wú)意義。
懸垂指針(dangling pointer)
刪除了指針?biāo)赶虻膶?duì)象后,該指針變成懸垂指針。懸垂指針指向曾經(jīng)存放對(duì)象的內(nèi)存,但該對(duì)象實(shí)際已經(jīng)不存在了。懸垂指針往往導(dǎo)致程序錯(cuò)誤,并且很難檢測(cè)。因此,在調(diào)用delete 釋放指針?biāo)笇?duì)象內(nèi)存后應(yīng)該立刻將指針置零。
4. Const 對(duì)象的動(dòng)態(tài)分配和回收
const 對(duì)象,必須在定義階段或動(dòng)態(tài)創(chuàng)建階段進(jìn)行初始化,并且初始化之后其值不能再修改。
與其他 const 對(duì)象的地址一樣,由于 new 返回的地址上存放的是 const 對(duì)象,因此該地址只能賦給指向 const 的指針。
// allocate and initialize a const object const int *pci = new const int(222); // initialize to 222 const int *pci2 = new const int(); // initialize to 0
盡管程序員不能改變 const 對(duì)象的值,但可撤銷對(duì)象本身。
delete pci; // ok: delete a const object
三種常見的程序錯(cuò)誤都與動(dòng)態(tài)內(nèi)存分配相關(guān):
1、刪除動(dòng)態(tài)分配內(nèi)存失敗,稱為內(nèi)存泄漏(memory leak)
2、讀寫已刪除的對(duì)象
3、對(duì)同一個(gè)內(nèi)存空間使用兩次 delete 表達(dá)式。當(dāng)兩個(gè)指針指向同一個(gè)動(dòng)態(tài)創(chuàng)建的對(duì)象,刪除時(shí)就會(huì)發(fā)生錯(cuò)誤。第二個(gè)指針的 delete 操作往往會(huì)破壞自由存儲(chǔ)區(qū)。
個(gè)人實(shí)踐部分:
#include <iostream>
#include <cstring>
using namespace std;
int main(void)
{
string str = "hello str";
// strNew points to dynamically allocated,
// initialized to empty string
string *strNew = new string;
cout<<"str object address: "<<&str<<endl;
cout<<"strNew pointer itself address: "<<&strNew<<endl;
cout<<"strNew pointer to address: "<<strNew<<endl;
// assignment
*strNew = "hello strNew";
cout<<"strNew pointer to address: "<<strNew<<endl;
// free memory
delete strNew;
cout<<"strNew pointer to address: "<<strNew<<endl;
strNew = NULL;
// point to other object
strNew = &str;
cout<<"strNew pointer to address: "<<strNew<<endl;
const int cvalue(10);
// iptr points to a const int object
const int *iptr = new const int(222);
cout<<"iptr value: "<<*iptr<<endl;
delete iptr;
iptr = NULL;
iptr = &cvalue;
cout<<"iptr value: "<<*iptr<<endl;
return 0;
}
一次運(yùn)行的結(jié)果如下:
str object address: 0x28ff24 strNew pointer itself address: 0x28ff20 strNew pointer to address: 0x602f70 strNew pointer to address: 0x602f70 strNew pointer to address: 0x602f70 strNew pointer to address: 0x28ff24 iptr value: 222 iptr value: 10
程序中間將原來(lái)指向 new 創(chuàng)建的對(duì)象的指針重定向到一般的變量,可以看到指針存放地址的改變。另外需要注意,在釋放 new 對(duì)象之前不要將指針重新指向某個(gè)其他對(duì)象,這樣會(huì)導(dǎo)致原來(lái)動(dòng)態(tài)創(chuàng)建的對(duì)象沒(méi)有指針指向它,無(wú)法釋放內(nèi)存空間。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
欄 目:C語(yǔ)言
下一篇:詳解C++中的vector容器及用迭代器訪問(wèn)vector的方法
本文標(biāo)題:C++表達(dá)式new與delete知識(shí)詳解
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/2308.html
您可能感興趣的文章
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)式函數(shù)庫(kù)
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)數(shù)怎么表達(dá)
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-用棧實(shí)現(xiàn)表達(dá)式求值的方法詳解
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10C#中split用法實(shí)例總結(jié)


