網站首頁 編程語言 正文
C++ new的用法
知識點小結
new其實就是告訴計算機開辟一段新的空間,但是和一般的聲明不同的是,new開辟的空間在堆上,而一般聲明的變量存放在棧上。
通常來說,當在局部函數中new出一段新的空間,該段空間在局部函數調用結束后仍然能夠使用,可以用來向主函數傳遞參數。
另外需要注意的是,new的使用格式,new出來的是一段空間的首地址。所以一般需要用指針來存放這段地址。
具體的代碼如下:
#include <iostream>
using namespace std;
int example1()
{
//可以在new后面直接賦值
int *p = new int(3);
//也可以單獨賦值
//*p = 3;
//如果不想使用指針,可以定義一個變量,在new之前用“*”表示new出來的內容
int q = *new int;
q = 1;
cout << q << endl;
return *p;
}
int* example2()
{
//當new一個數組時,同樣用一個指針接住數組的首地址
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()
{
//這里是用一個結構體指針接住結構體數組的首地址
//對于結構體指針,個人認為目前這種賦值方法比較方便
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 是不拋出異常的運算符new的形式。nothrow new在失敗時,返回NULL。定義如下:
1 void * operator new(std::size_t, const std::nothrow_t&) throw();
2 void operator delete(void*) throw();
placement new 意即“放置”,這種new允許在一塊已經分配成功的內存上重新構造對象或對象數組。placement new不用擔心內存分配失敗,因為它根本不分配內存,它做的唯一一件事情就是調用對象的構造函數。定義如下:
1 void* operator new(size_t, void*);
2 void operator delete(void*, void*);
palcement new 的主要用途就是反復使用一塊較大的動態分配的內存來構造不同類型的對象或者他們的數組。placement new構造起來的對象或其數組,要顯示的調用他們的析構函數來銷毀,千萬不要使用delete。
示例
- plain new
char *getMemory(unsigned long size) ??
{ ? ?
? ? char * p = new char[size]; ??
? ? return p;?
} ??
void main(void) ??
{
? ? try{ ??
? ? ? ? char * p = getMemory(1000000); ? ?// 可能發生異常
? ? ? ? // ... ??
? ? ? ? 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時要加(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僅僅是首址相同,所構建的對象可以類型不同。所“放置”的空間應小于原空間,以防不測。當”放置new”超過了申請的范圍,Debug版下會掛機,但Release版竟然能運行而不出錯!
該運算符的作用是:只要第一次分配成功,不再擔心分配失敗。
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 ?然后釋放對象 ... ??
? ? delete [] p; ? ?// 只釋放空間,不再析構對象。
}
注意:使用該運算符構造的對象或數組,一定要顯式調用析構函數,不可用delete代替析構,因為placement new 的對象的大小不再與原空間相同。
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; // 錯誤
? ? q->ADT::~ADT(); ?// 顯式調用析構函數,僅釋放對象
? ? delete [] p; ? ? // 最后,再用原指針來釋放內存
}
placement new 的主要用途就是可以反復使用一塊已申請成功的內存空間。這樣可以避免申請失敗的徒勞,又可以避免使用后的釋放。
特別要注意的是對于 placement new 絕不可以調用的delete, 因為該new只是使用別人替它申請的地方(只是個租房戶,不是房主。無權將房子賣掉)。釋放內存是nothrow new的事,即要使用原來的指針釋放內存。
原文鏈接:https://blog.csdn.net/weixin_41232202/article/details/96452228
相關推薦
- 2022-02-17 MacOS Catalina啟用三指拖移
- 2022-12-24 如何計算?tensorflow?和?pytorch?模型的浮點運算數_python
- 2022-03-17 .NET?6開發TodoList應用引入第三方日志庫_實用技巧
- 2023-02-12 詳解C#如何實現隱式類型轉換_C#教程
- 2022-06-14 C語言深入淺出講解順序表的實現_C 語言
- 2022-04-17 Bootstrap typeahead自動補全插件的坑
- 2023-11-12 jetson nano報錯Cannot allocate memory的問題——解決辦法
- 2022-07-14 實現一個random?shuffle算法示例_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支