首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Effective C++ 條款 14:資源管理類別的複製行為深度解析

     編輯:關於C++

核心觀念:RAII 與複製語意的關鍵抉擇

在 C++ 中,auto_ptr(已棄用)與 std::shared_ptr 等智慧指標專門管理堆積記憶體資源。然而,現實世界中並非所有資源都來自堆積,例如檔案控制代碼、互斥鎖、網路通訊端、資料庫連線等。這時我們需要自行設計資源管理類別,而 RAII(Resource Acquisition Is Initialization) 是此類設計的基石:資源在建構函式中獲取,在解構函式中釋放,確保不會發生資源洩漏。

案例研究:鎖管理類別 Lock

假設我們使用 C 風格 API 操作互斥鎖:

void lock(Mutex* pm);   // 鎖定 pm 指向的互斥鎖
void unlock(Mutex* pm); // 解除鎖定

為了確保鎖一定會被釋放,我們設計一個 RAII 風格的 Lock 類別:

class Lock {
public:
    explicit Lock(Mutex* pm) : mutexPtr(pm) { lock(mutexPtr); } // 獲取資源
    ~Lock() { unlock(mutexPtr); }                                // 釋放資源
private:
    Mutex* mutexPtr;
};

使用方式符合 RAII 慣例:

Mutex m;
{
    Lock ml(&m); // 鎖定互斥鎖,進入臨界區
    // ... 執行臨界區操作
} // 區塊結束,ml 解構,自動解除鎖定

複製語意的四種選擇

當 Lock 物件被複製時,會發生什麼事?

Lock ml1(&m);      // 鎖定 m
Lock ml2(ml1);     // 複製 ml1 到 ml2,這該怎麼辦?

資源管理類別的複製行為取決於其所管理資源的複製特性。主要有四種策略:

  1. 禁止複製:將複製建構函式與複製指派運算子宣告為 private(C++98)或標記為 = delete(C++11)。這是 std::unique_ptr、std::lock_guard 的做法,適用於獨占所有權的資源。
  2. 引用計數法:多個物件共享同一資源,最後一個物件銷毀時釋放資源。這是 std::shared_ptr 的核心機制,適用於共享所有權的場景。
  3. 複製底層資源:深層複製資源本身。例如複製一個檔案控制代碼可能意味著開啟同一檔案的新控制代碼;複製字串則分配新記憶體並複製內容。適用於資源可獨立複製且語意合理的情況。
  4. 轉移所有權:複製操作實際上將資源所有權從來源轉移給目標,來源不再擁有資源。這是 std::auto_ptr(已棄用)的行為,現代 C++ 推薦使用移動語意(std::move)來明確表達所有權轉移。

設計原則總結

複製 RAII 物件必須一並複製其所管理的資源,因此資源的複製行為決定了 RAII 物件的複製行為。

最普遍、最常見的 RAII 類別複製行為是:抑制複製(如 std::unique_ptr、std::lock_guard)與 引用計數(如 std::shared_ptr)。但根據資源特性,其他行為也可能是合理的實現選項。設計時務必明確資源的所有權語意,並據此選擇或組合上述策略。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved