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

vector 容器 capacity 與 sizeof 疑難雜症深度解析

     編輯:關於C++

前言

std::vector 的動態增長策略與對象大小是 C++ 面試與實戰中的高頻考點。本文通過兩個具體案例,深度剖析 capacity 行為差異與 sizeof(vector) 跨編譯器差距的根本原因。

案例一:傳值參數導致 capacity 異常

原始代碼(正常)

vector<int> vec;
for (size_t i = 0; i != 24; ++i) vec.push_back(i);
cout << "size:" << vec.size() << ",capacity:" << vec.capacity();
vec.reserve(50);
while (vec.size() != vec.capacity()) vec.push_back(0);
cout << "size:" << vec.size() << ",capacity:" << vec.capacity();
vec.push_back(0);
cout << "size:" << vec.size() << ",capacity:" << vec.capacity();

輸出:size:24,capacity:32 → size:50,capacity:50 → size:51,capacity:100(典型 2 倍增長)

修改後代碼(異常)

void print(vector<int> vec) {  // 傳值!會拷貝構造
    cout << "size:" << vec.size() << ",capacity:" << vec.capacity();
}

int main() {
    vector<int> vec;
    print(vec);                    // 拷貝 1:空 vector
    for (size_t i = 0; i != 24; ++i) vec.push_back(i);
    print(vec);                    // 拷貝 2:size=24, capacity=32
    vec.reserve(50);
    while (vec.size() != vec.capacity()) vec.push_back(0);
    print(vec);                    // 拷貝 3:size=50, capacity=50
    vec.push_back(0);
    print(vec);                    // 拷貝 4:size=51, capacity=100
}

輸出:size:0,capacity:0 → size:24,capacity:32 → size:50,capacity:50 → size:51,capacity:100

根因:拷貝構造函數語義

vector 的拷貝構造函數 複製元素內容,但不複製多餘容量。新 vector 的 capacity() == size()。

每次調用 print(vec) 都創建臨時副本,輸出的是副本的 capacity,而非原對象。原對象增長邏輯完全正常,只是觀測點錯了。

修正:傳常量引用

void print(const vector<int>& vec) {  // 無拷貝,零開銷
    cout << "size:" << vec.size() << ",capacity:" << vec.capacity();
}

案例二:sizeof(vector) 跨編譯器差異

測試結果

編譯器/平台sizeof(vector<int>)內部結構推測
VC6.0 (32-bit)16 bytes3 指針:_First, _Last, _End
VS2008 (32-bit)20 bytes3 指針 + 1 size_type 或對齊填充
G++ (Linux 32-bit)12 bytes3 指針(無額外字段)
G++ (Linux 64-bit)24 bytes3 指針(各 8 bytes)

標準規定與實現自由

  • C++ 標準未規定 sizeof(vector) 具體值
  • 只要求 vector 滿足容器需求(迭代器、複雜度保證等)
  • 各標準庫實現自由選擇內部佈局:
// 典型實現(libstdc++)
template <typename T, typename Alloc>
class vector {
    T* _M_start;      // 首元素
    T* _M_finish;     // 末尾後一位
    T* _M_end_of_storage; // 容量末尾
};

// VC 可能額外存儲 allocator 或 size_type
// VS2008 引入 _SCL_SECURE 迭代器檢查可能增加字段

關鍵結論

  1. 不可依賴 sizeof(vector) 進行序列化、內存佈局假設或跨模塊傳遞
  2. 32/64 位差異巨大:指針大小變化直接導致對象大小翻倍
  3. 調試版 vs 發布版 可能不同(如 VC 的迭代器檢查字段)

總結

  • capacity 觀測異常源於傳值參數觸發拷貝構造,改用 const& 即可
  • sizeof(vector) 是實現細節,跨編譯器/平台/版本均不保證一致
  • 標準庫實現自由度是 C++ 性能與抽象平衡的體現,開發者應依賴接口契約而非內存佈局
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved