首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MFC CString 內部數據結構解析:動態數組而非鏈表

     編輯:程式設計綜合問答

結論

CString 內部使用引用計數的動態字符數組(類似 Copy-On-Write),而非鏈表。

核心結構 (簡化)

struct CStringData {
    long nRefs;      // 引用計數
    int nDataLength; // 當前字符數
    int nAllocLength; // 分配緩衝區長度
    // 緊隨其後是字符數組:TCHAR data[nAllocLength + 1];
};

class CString {
    CStringData* m_pData; // 指向共享數據塊
    // 小字符串優化 (SSO):短字符串直接存儲在對象內部,不分配堆
};

關鍵機制

  1. 引用計數 (Ref Count):賦值/傳參時 InterlockedIncrement(&nRefs),銷毀時遞減,歸零才 free。
  2. 寫時復制 (COW):調用非 const 方法(如 SetAt, Append)前檢查 nRefs > 1,是則深拷貝一份新緩衝區。
  3. 小字符串優化 (SSO):VS2010+ 針對長度 ≤ 15 (ANSI) / 7 (Unicode) 的字符串,直接存儲在 CString 對象內部(佔用 16/32 字節),零堆分配。
  4. 幂增長:擴容按 1.5x/2x 分配,減少重分配次數。

為何不用鏈表?

操作動態數組 (CString)鏈表
隨機訪問O(1)O(n)
內存局部性極佳 (CPU 緩存友好)差 (指針跳轉)
拼接O(n) 單次分配O(1) 但需遍歷求長
內存碎片少多 (每節點單獨分配)

驗證代碼

CString s1 = _T("Hello");
CString s2 = s1; // 僅增加引用計數
ASSERT(s1.GetData() == s2.GetData()); // 指向同一塊內存

s2 += _T(" World"); // 觸發 COW,s2 獨享新緩衝區
ASSERT(s1.GetData() != s2.GetData());

理解底層結構有助於避免性能陷阱:如循環中大量 s += ch 應預先 s.GetBufferSetLength(n) 預分配。

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