C++中new的用法及說(shuō)明
C++ new的用法
知識(shí)點(diǎn)小結(jié)
new其實(shí)就是告訴計(jì)算機(jī)開辟一段新的空間,但是和一般的聲明不同的是,new開辟的空間在堆上,而一般聲明的變量存放在棧上。
通常來(lái)說(shuō),當(dāng)在局部函數(shù)中new出一段新的空間,該段空間在局部函數(shù)調(diào)用結(jié)束后仍然能夠使用,可以用來(lái)向主函數(shù)傳遞參數(shù)。
另外需要注意的是,new的使用格式,new出來(lái)的是一段空間的首地址。所以一般需要用指針來(lái)存放這段地址。
具體的代碼如下:
#include <iostream>
using namespace std;
int example1()
{
//可以在new后面直接賦值
int *p = new int(3);
//也可以單獨(dú)賦值
//*p = 3;
//如果不想使用指針,可以定義一個(gè)變量,在new之前用“*”表示new出來(lái)的內(nèi)容
int q = *new int;
q = 1;
cout << q << endl;
return *p;
}
int* example2()
{
//當(dāng)new一個(gè)數(shù)組時(shí),同樣用一個(gè)指針接住數(shù)組的首地址
int *q = new int[3];
for(int i=0; i<3; i++)
q[i] = i;
return q;
}
struct student
{
string name;
int score;
};
student* example3()
{
//這里是用一個(gè)結(jié)構(gòu)體指針接住結(jié)構(gòu)體數(shù)組的首地址
//對(duì)于結(jié)構(gòu)體指針,個(gè)人認(rèn)為目前這種賦值方法比較方便
student *stlist = new student[3]{{"abc", 90}, {"bac", 78}, {"ccd", 93}};
return stlist;
}
int main()
{
int e1 = example1();
cout <<"e1: "<< e1 << endl;
int *e2 = example2();
for(int i=0; i<3; i++)
cout << e2[i] << " ";
cout << endl;
student *st1 = example3();
for(int i=0; i<3; i++)
cout << st1[i].name << " " << st1[i].score << endl;
return 0;
}new的三種使用方法
概念
在C++中new的三種用法包括:plain new, nothrow new 和 placement new。
plain new 就是我們最常使用的new的方式,在C++中的定義如下:
1 void* operator new(std::size_t) throw(std::bad_alloc); ? 2 void operator delete( void *) throw();
plain new在分配失敗的情況下,拋出異常std::bad_alloc而不是返回NULL,因此通過判斷返回值是否為NULL是徒勞的。
nothrow new 是不拋出異常的運(yùn)算符new的形式。nothrow new在失敗時(shí),返回NULL。定義如下:
1 void * operator new(std::size_t, const std::nothrow_t&) throw(); 2 void operator delete(void*) throw();
placement new 意即“放置”,這種new允許在一塊已經(jīng)分配成功的內(nèi)存上重新構(gòu)造對(duì)象或?qū)ο髷?shù)組。placement new不用擔(dān)心內(nèi)存分配失敗,因?yàn)樗静环峙鋬?nèi)存,它做的唯一一件事情就是調(diào)用對(duì)象的構(gòu)造函數(shù)。定義如下:
1 void* operator new(size_t, void*); 2 void operator delete(void*, void*);
palcement new 的主要用途就是反復(fù)使用一塊較大的動(dòng)態(tài)分配的內(nèi)存來(lái)構(gòu)造不同類型的對(duì)象或者他們的數(shù)組。placement new構(gòu)造起來(lái)的對(duì)象或其數(shù)組,要顯示的調(diào)用他們的析構(gòu)函數(shù)來(lái)銷毀,千萬(wàn)不要使用delete。
示例
- plain new
char *getMemory(unsigned long size) ??
{ ? ?
? ? char * p = new char[size]; ??
? ? return p;?
} ??
void main(void) ??
{
? ? try{ ??
? ? ? ? char * p = getMemory(1000000); ? ?// 可能發(fā)生異常
? ? ? ? // ... ??
? ? ? ? delete [] p; ??
? ? } ??
? ? catch(const std::bad_alloc & ex) ??
? ? {
? ? ? ? cout << ex.what();
? ? } ??
}- nowthrow new
void func(unsinged long length) ??
{
? ? unsinged char * p = new(nothrow) unsinged char[length]; ??
? ? // 在使用這種new時(shí)要加(nothrow) ,明示不使用異常處理 。
?
? ? if (p == NULL) ?// 因不拋異常,故定要檢查
? ? ? ? cout << "allocte failed !"; ??
? ? ? ? // ... ??
? ? delete [] p;
}- placement new
void main() ??
{ ?
? ? using namespace std; ??
? ? char * p = new(nothrow) char [4]; ??
? ? if (p == NULL) ??
? ? {
? ? ? ? cout << "allocte failed" << endl; ?
? ? ? ? exit( -1 );
? ? } ??
? ? // ... ??
? ? long * q = new (p) long(1000); ??
? ? delete []p; ? ?// 只釋放 p,不要用q釋放。
}p和q僅僅是首址相同,所構(gòu)建的對(duì)象可以類型不同。所“放置”的空間應(yīng)小于原空間,以防不測(cè)。當(dāng)”放置new”超過了申請(qǐng)的范圍,Debug版下會(huì)掛機(jī),但Release版竟然能運(yùn)行而不出錯(cuò)!
該運(yùn)算符的作用是:只要第一次分配成功,不再擔(dān)心分配失敗。
void main() ??
{
? ? using namespace std; ??
? ? char * p = new(nothrow) char [100]; ??
? ? if (p == NULL) ??
? ? { ?
? ? ? ? cout << "allocte failed" << endl;
? ? ? ? exit(-1);
? ? } ??
? ? long * q1 = new (p) long(100); ??
? ? // 使用q1 ?... ??
? ? int * q2 = new (p) int[100/sizeof(int)]; ??
? ? // 使用q2 ... ??
? ? ADT * q3 = new (p) ADT[100/sizeof(ADT)]; ??
? ? // 使用q3 ?然后釋放對(duì)象 ... ??
? ? delete [] p; ? ?// 只釋放空間,不再析構(gòu)對(duì)象。
}注意:使用該運(yùn)算符構(gòu)造的對(duì)象或數(shù)組,一定要顯式調(diào)用析構(gòu)函數(shù),不可用delete代替析構(gòu),因?yàn)閜lacement new 的對(duì)象的大小不再與原空間相同。
void main() ??
{ ?
? ? using namespace std; ??
? ? char * p = new(nothrow) char [sizeof(ADT)+2]; ??
? ? if (p == NULL) ??
? ? { ?
? ? ? ? cout << "allocte failed" << endl;
? ? ? ? exit(-1);?
? ? }?
? ? // ...?
? ? ADT * q = new (p) ADT;?
? ? // ...?
? ? // delete q; // 錯(cuò)誤
? ? q->ADT::~ADT(); ?// 顯式調(diào)用析構(gòu)函數(shù),僅釋放對(duì)象
? ? delete [] p; ? ? // 最后,再用原指針來(lái)釋放內(nèi)存
}placement new 的主要用途就是可以反復(fù)使用一塊已申請(qǐng)成功的內(nèi)存空間。這樣可以避免申請(qǐng)失敗的徒勞,又可以避免使用后的釋放。
特別要注意的是對(duì)于 placement new 絕不可以調(diào)用的delete, 因?yàn)樵搉ew只是使用別人替它申請(qǐng)的地方(只是個(gè)租房戶,不是房主。無(wú)權(quán)將房子賣掉)。釋放內(nèi)存是nothrow new的事,即要使用原來(lái)的指針釋放內(nèi)存。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++調(diào)用C接口的實(shí)現(xiàn)示例
這篇文章主要介紹了C++調(diào)用C接口的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
如何用C寫一個(gè)web服務(wù)器之I/O多路復(fù)用
本文主要介紹了如何用C寫一個(gè)web服務(wù)器之I/O多路復(fù)用,本次選擇了 I/O 模型的優(yōu)化,因?yàn)樗欠?wù)器的基礎(chǔ),這個(gè)先完成的話,后面的優(yōu)化就可以選擇各個(gè)模塊來(lái)進(jìn)行,不必進(jìn)行全局化的改動(dòng)了。2021-05-05
C語(yǔ)言初階之?dāng)?shù)組詳細(xì)介紹
大家好,本篇文章主要講的是C語(yǔ)言初階之?dāng)?shù)組詳細(xì)介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12

