網站首頁 編程語言 正文
primitives
分配 | 釋放 | 屬于 | 是否可重載 |
---|---|---|---|
malloc() | free() | C | 不可 |
new | delete | C++表達式 | 不可 |
::operator new() | ::operator delete() | C++函數(shù) | 可 |
allocator::allocate() | allocator::deallocate() | C++標準庫 | 可自由設計搭配容器 |
new 和 delete
C/C++中的new和delete的實現(xiàn)過程
operator new():第一個參數(shù)表示大小,第二個參數(shù)表示保證這個函數(shù)不拋出異常。
注意:構造函數(shù)不能直接調用,而析構函數(shù)可以直接調用。
new[] 與 delete[] 要搭配使用,未搭配使用可能會內存泄漏,泄露的是指針所指向的地方。
析構的時候次序會逆反。
對于 析構函數(shù) 沒有意義,new[] 是否對應 delete[] 不重要,但是 當析構函數(shù)有意義時,必須對應。
placement new
placement new 允許我們將對象建構在一個已經分配的內存中。并且沒有對應的placement delete。
第一部分,本來是分配內存,現(xiàn)在已經分配好了,所以直接返回。
重載 operator new
::operator new 和::operator delete 全部可以重載,但是不推薦。類中 operator new 也可以重載,實現(xiàn)所需功能,這是最常用的。
class Foo{
public:
void *operator new(size_t);
void operator delete(void*,size_t);
//....
};
注意,可以寫出多個版本,前提是每一個版本的聲明都必須有獨特的參數(shù)列。(第一參數(shù)必須是size_t)只有new所調用的ctor 拋出異常,才會調用這些重載版的 operator delete()。
即使 operator delete() 未能一一對應operator new() 也不會出現(xiàn)任何報錯。換句話說:放棄處理構造函數(shù)拋出的異常。
per-class allocator
一:
想利用類內重載operator new去接管內存的分配,然后利用內存池的觀念【即創(chuàng)建出一大段連續(xù)空間的內存,然后將其切割成一小段一小段】,將創(chuàng)建的元素對象放在內存池切分好的各分段小內存片中,這樣避免了多次調用new而造成生成多個帶有cookie的內存空間。通過內存池的觀念,可以生成一大段只帶有兩個頭尾cookie的內存空間,而該一大段內存空間又被切分成每一小段的內存空間,且其中的每一小段內存空間片都可以共享這一整體的cookie信息。
因為為了能將一大段內存空間切分成一小段一小段,然后通過單向鏈表的形式串接起來,所以必須多引入一個Screen* next指針。但這又會增加class Screen的大小【增加了4字節(jié)】。
二:第一個占用了一個指針,浪費空間
這個版本通過union關鍵字來減少使用next而所占耗的內存!
注意:上面兩個版本的operator delete操作都沒有將內存空間回收還回給系統(tǒng),而是仍然存在的。雖然operator delete操作沒有將這些分配的內存空間釋放掉,但其仍在控制中即仍可繼續(xù)重新使用【只不過freeStore或headOfFreeList此時又重新跑回整個一大塊內存空間的頭端】,所以不算內存泄漏!
三:上面的版本不具有復用性
將分配特定尺寸區(qū)塊的memory allocator包裝成一個class allocator,這樣每個allocator object都是個分配器,體內維護一個free lists,不同類(如下面的class Foo,class Goo等) 里面調用生成的各自allocator objects維護不同的free lists。
由上知,class Foo或class Goo其operator new或operator delete最終調用的都是allocator object所維護的free list而進行操作的!
另外,class Foo或class Goo中,應注意到:
static allocator myAlloc,即myAlloc必須是個靜態(tài)成員變量,且在類外定義(賦初值)。如果其不是靜態(tài)成員變量時,則在構建class Foo類對象時,是沒辦法調用到myAlloc的。因為非靜態(tài)成員變量只能通過對象調用【但此時Foo對象還沒生成又如何調用!!】。而myAlloc又是用來生成Foo類對象的,所以得通過類名調用即應設置為static類型。
而class allocator的如下:
class allocator{
private:
struct obj{
struct obj* next;
};
public:
static void* allocate(size_t);
static void deallocate(void*, size_t);
private:
obj* freeStore = nullptr;
const int CHUNK = 5; // 標準庫一般設置為20
};
void* allocator::allocate(size_t size){
obj* p;
if(!freeStore){
// linked list為空,則申請一大塊
size_t chunk = CHUNK * size;
freeStore = p =(obj*)malloc(chunk); // 這里直接調用malloc進行分配空間
// 將分配的一大塊切分成5小段,并串接起來
for(int i = 0; i < (CHUNK - 1); ++i){
p->next = (obj*)((char*)p + size);
p = p->next;
// 上面這兩步相當于p->next = p + 1,
// 只不過這里需要適應不同的類下的操作,因而設置成這種形式!!
}
p->next = nullptr; // 最后一小段的下一個位置指向空
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
void allocator::deallocate(void* p, size_t){
// 將要刪除的*p的位置調整為free list的頭端
((obj*)p)->next = freeStore;
freeStore = (obj*)p;
}
四、macro for static allocator(per-class allocator 4)
由第三版本知,其黃色部分我們想將其定義為宏操作,進一步簡化代碼內容:
// DECLARE_POOL_ALLOC ?used in class definition
#define DECLARE_POOL_ALLOC()\
public:\
?? ?void* operator new(size_t size){
?? ??? ?return myAlloc.cllocate(size);
?? ?}\
?? ?void operator delete(void* p){
?? ??? ?myAlloc.deallocate(p, 0);
?? ?}\
protected:\
?? ?static allocator myAlloc;// IMPLEMENT_POOL_ALLOC ? used in class implementation file
#define IMPLEMENT_POOL_ALLOC(class_name)\
?? ?allocator class_name::myAlloc;
使用實例如圖所示:
在類內進行宏聲明,在類外進行宏定義【告訴編譯器傳入參數(shù)的class type】
New Handler
=default,=delete
一個是需要默認版本,另一個是這個函數(shù)我不要。
這兩個函數(shù)不僅使用構造,同時適用于 operator new 和 operator delete。
原文鏈接:https://blog.csdn.net/qq_43142509/article/details/125465186
相關推薦
- 2022-03-05 C#多線程用法詳解_C#教程
- 2022-12-05 Golang中的錯誤處理的示例詳解_Golang
- 2023-07-26 vscode中配置代碼片段
- 2024-04-03 objectMapper(字符串轉對象)
- 2022-12-15 Rust實現(xiàn)一個表達式Parser小結_Rust語言
- 2023-01-20 python如何求兩數(shù)之和及多數(shù)之和_python
- 2022-09-27 阿里云官方Redis開發(fā)規(guī)范總結_Redis
- 2023-12-11 Mybatis結果集映射ResultMap
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支