在 C++ 開發中,標準模板庫(STL)的容器特性、vector 的記憶體重新分配機制,以及動態/靜態程式庫的建置與使用,始終是開發者常遇到的難點。本文將針對這些主題,提供深入淺出的解析與最佳實踐建議。
std::list 內部以雙向鏈表實現,其迭代器僅支援雙向移動(++、--),不提供隨機存取運算子(+、-、+=、-=)。若需將迭代器前進指定距離,早期常見做法是手寫迴圈:
list<int>::const_iterator it = myList.begin();
for (int i = 0; i < len; ++i) ++it;
但 C++ 標準庫已提供通用算法 std::advance,它能根據迭代器類別自動選擇最佳移動策略:對隨機存取迭代器(如 vector、deque)直接跳躍;對雙向/前向迭代器(如 list、map)則逐步遞增。建議直接使用 std::advance(it, len),程式碼更簡潔且具可移植性。
這兩個函數本質不同:
push_back() 或 insert()。val(或預設建構函式)填充新元素;調用後可直接用 operator[] 或迭代器存取。範例:
vector<int> vec;
vec.reserve(100); // 僅預留空間
for (int i=0; i<100; ++i) vec.push_back(i); // 實際構造
vec.resize(102); // 擴大至 102,新元素以 0 填充
vec[100] = 1; vec[101] = 2; // 直接存取
vector 在 push_back 導致容量不足時會重新分配記憶體並移動所有元素,導致指向元素內部的指標/引用失效。典型錯誤範例:
struct Node { int val; Node* prev; };
vector<Node> vec;
for (int i=0; i<count; ++i) {
Node n; n.prev = &vec.back(); // 危險:vec 可能重新分配
vec.push_back(n);
}
解決方案:
vec.reserve(足夠大小) 避免重新分配。std::list 或 std::deque(其迭代器/指標在插入時不失效)。在 Visual C++ .NET 中,專案類型選擇「靜態程式庫」或「動態連結庫」即可建立空專案。
extern "C" 回傳型別 函數名(參數...);(extern "C" 防止 C++ 名稱修飾)。.lib,連同標頭檔提供給使用者。.lib 路徑,並 #include 標頭檔即可呼叫。
extern "C" __declspec(dllexport) 回傳型別 函數名(參數...);.dll、.lib(匯入程式庫)與標頭檔,三者皆需部署。.lib,但標頭檔中對應函數需宣告為 __declspec(dllimport)(常透過巨集切換)。.dll。關鍵差異:
cout),除錯較不便。善用 std::advance 替代手寫迴圈;明確區分 reserve/resize 用途;預留 vector 容量或改用索引以防指標失效;根據部署需求選擇靜態或動態程式庫,並正確處理導出/導入宣告。掌握這些核心概念,能大幅減少 C++ 開發中的常見坑洞。