std::vector 的動態增長策略與對象大小是 C++ 面試與實戰中的高頻考點。本文通過兩個具體案例,深度剖析 capacity 行為差異與 sizeof(vector) 跨編譯器差距的根本原因。
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<int>) | 內部結構推測 |
|---|---|---|
| VC6.0 (32-bit) | 16 bytes | 3 指針:_First, _Last, _End |
| VS2008 (32-bit) | 20 bytes | 3 指針 + 1 size_type 或對齊填充 |
| G++ (Linux 32-bit) | 12 bytes | 3 指針(無額外字段) |
| G++ (Linux 64-bit) | 24 bytes | 3 指針(各 8 bytes) |
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 迭代器檢查可能增加字段
capacity 觀測異常源於傳值參數觸發拷貝構造,改用 const& 即可sizeof(vector) 是實現細節,跨編譯器/平台/版本均不保證一致