網站首頁 編程語言 正文
以對象管理資源
class A{...};
//工廠函數createA來提供特定的A對象
A* createA();
//壞情況
void f(){
A* p=createA();
...
delete p;//如何在delete之前程序先return了,則無法delete
}
//為了確保資源釋放 將資源放進對象內 利用對象的析構函數來釋放
void f(){
std::shared_ptr<A> p(createA());
...
//程序結束后會經shared_ptr的析構函數釋放
}
auto_ptr已經被廢除,主要原因是其拷貝會造成所以權轉移,所以使用shared_ptr更好
以對象管理資源的關鍵想法:
1、獲得資源后立刻放進管理對象內
2、管理對象運用析構函數釋放資源
注意是:shared_ptr和auto_ptr兩者都在析構函數上使用delete而不是delete[],所以在動態分配的數組上使用它們不好。當然我覺得還是少用動態數組,用vector,string啥的就能代替咯。
在資源管理類中小心copy行為
復制RAII對象時有兩種選擇:
1、禁止復制--------將copying操作聲明為private
class Lock:private Uncopyable{
public:
....
};
2、對底層資源祭出"引用計數法"--------即shared_ptr
class Lock{
public:
explicit Lock(Mutex* pm):mutexPtr(pm,unlock)//unlock函數為刪除器
{
lock(mutexPtr.get());
}
private:
shared_ptr<Mutex>mutexPtr;
}
復制底部資源:需要資源管理類對象的唯一理由是不需要某個復件資源時確保被釋放,在此情況下復制資源管理類對象,應該也復制其所包括的資源,即深拷貝------當一個對象被復制時,不論指針或其所指內存都會被制作出一個復件,即深拷貝。
轉移底部資源所有權:auto_ptr,你只希望有一個RAII對象指向一個未加工資源,即使被復制也是如此。
在資源管理類中提供對原始資源的訪問
前提:智能指針其實是一個類
shared_ptr<A>p(createA());
//假如有以下函數
int func(const A* pi);
//如下調用錯誤 因為p是一個智能指針不是一個指向A的指針
int f=func(p);
//調用get函數返回原始資源
int f=func(p.get());
智能指針重載了指針取值操作符(->,*) 允許隱式轉換到原始指針
//例如A有一個函數,p是一個指向A的智能指針
int A::getNum();
//如下調用合格,其實是發生了一個智能指針到原始指針的隱式轉換
int num=p->getNum();
一般而言顯示轉換比較安全,隱式轉換客戶使用方便。
成對使用new和delete時要采用相同形式
delete的最大問題在于:即將被刪除的內存之內究竟有多少個對象
即:被刪除的那個指針是指的單一對象還是成對數組?
string* p1=new string;
string* p2=new string[100];
delete p1;
delete[] p2;
規則很簡單:new中用了[],delete就要用[]
以獨立語句將new對象置入智能指針
假設有一個函數來揭示處理程序的優先權,另一個函數用來在動態分配所得的Widget上進行某些帶有優先權的處理
int priority();
void processWidget(shared_ptr<Widget>pw,int priority);
//錯誤
processWideget(new Widget,priority());
//因為shared_ptr的構造函數需要一個原始指針,該構造函數是explicit,無法隱式轉換
processWideget(shared_ptr<Widget>(new Widget),priority());//可以
但是編譯器執行順序不確定,調用該函數前,編譯器需要:
調用priority,執行new Widget,shared_ptr構造函數
但調用priority的順序可以是第一第二或第三(new 和智能指針的先后順序不能變)
如何是先new,后priority,再shared_ptr,萬一priority調用失常,則new出來的指針遺失,尚未置入shaerd_ptr的構造函數,則會資源泄漏。
因此分開寫最好:
shared_ptr<Widget>pw(new Wideget);
processWidget(pw,priority());
原文鏈接:https://blog.csdn.net/RolleX/article/details/126972818
相關推薦
- 2022-10-16 python列表倒序的幾種方法(切片、reverse()、reversed())_python
- 2022-08-30 c語言學習——動態內存分配
- 2022-04-12 Oracle?Session每日統計功能實現_oracle
- 2022-11-12 Shell實現字符串處理的方法詳解_linux shell
- 2022-11-10 詳解C++?左值引用與?const?關鍵字_C 語言
- 2022-11-01 Flask?sqlalchemy一對多與多對一與一對一及多對多關系介紹_python
- 2024-01-15 SpringMVC之@InitBinder注解詳解
- 2023-10-15 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同步修改后的遠程分支