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

C++/VC++ 疑難雜症解析:STL 容器陷阱、靜態/動態庫實戰與迭代器進階

     編輯:關於C++

一、std::list 迭代器隨機移動:std::advance 才是正解

list 內部為雙向鏈表,迭代器僅支援 ++/--,不支援 +/-/+=/-=。手寫迴圈移動雖可行,但 std::advance 是通用標準做法:

#include <list>
#include <iterator> // advance 定義於此
std::list<int> myList = {1,2,3,4,5};
auto it = myList.begin();
std::advance(it, 3);  // 向前移動 3 位置,O(n)

advance 會根據迭代器類別自動選擇最佳策略:隨機存取迭代器(vector、deque)O(1) 跳躍;雙向/前向迭代器(list、map)O(n) 逐步移動。無需關心底層容器型別,程式碼更通用。

二、vector::resize() vs reserve():本質區別

特性reserve(n)resize(n)resize(n, val)
記憶體預留是是是
建構元素否是(預設構造)是(複製 val)
size() 變化不變變為 n變為 n
後續新增方式push_back/insertoperator[] / 迭代器operator[] / 迭代器

std::vector<int> v;
v.reserve(100);      // capacity=100, size=0
for (int i=0; i<100; ++i) v.push_back(i); // 逐個建構
v.resize(102);       // size=102, 新增 2 個 value=0 的元素
v[100] = 1;          // 直接存取有效
v[101] = 2;

口訣:reserve 只備容量,resize 真建元素。

三、vector 記憶體重新配置導致指標失效

危險代碼


struct Node { int id; Node* prev; };
std::vector<Node> vec;
for (int i=0; i<count; ++i) {
    Node n; n.prev = &vec[some_index]; // 危險!
    vec.push_back(n); // 可能觸發重新配置,prev 變懸空指標
}

兩種解決方案

  1. 預留足夠容量:vec.reserve(count); 避免重新配置
  2. 改用索引而非指標:size_t prev_idx; 索引不受重新配置影響

原則:只要 vector 可能增長,絕不儲存元素內部指標/參考。

四、靜態庫 vs 動態庫:建立與使用完整流程

靜態庫 (.lib)


// MyLib.h
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif

extern "C" MYLIB_API int Add(int a, int b); // C 連結防止名稱修飾

// MyLib.cpp
#include "MyLib.h"
extern "C" MYLIB_API int Add(int a, int b) { return a + b; }

使用者專案:

  • 包含 MyLib.h
  • 連結器 → 輸入 → 附加相依性:加入 MyLib.lib
  • 編譯產出 EXE,無需部署額外檔案

動態庫 (.dll + .lib)

介面宣告差異:


// DllLib.h
#ifdef DLLLIB_EXPORTS
#define DLLLIB_API __declspec(dllexport)
#else
#define DLLLIB_API __declspec(dllimport)
#endif

extern "C" DLLLIB_API int Add(int a, int b);

建置產出 DllLib.dll、DllLib.lib(導入庫)、DllLib.h。
使用者專案:

  • 連結器輸入加入 DllLib.lib
  • 部署時需攜帶 DllLib.dll
  • 或動態載入:LoadLibrary + GetProcAddress,無需 .lib/.h

關鍵差異總結

特性靜態庫動態庫
程式碼複製連結時複製進 EXE執行時共享單一副本
部署檔案僅 EXEEXE + DLL
更新維護需重新編譯 EXE替換 DLL 即可(介面相容)
巢狀依賴不能包含其他庫可包含其他靜態/動態庫
除錯便利性直接單步進入需載入符號表,稍繁瑣

注意:DLL 內避免使用 cout 等螢幕輸出,否則主控台應用可能無輸出、GUI 應用可能死鎖。

總結

  • std::advance 統一迭代器移動介面,勿手寫迴圈
  • reserve/resize 語義截然不同,按需選擇
  • Vector 成長會失效指標/參考,用索引或預留容量規避
  • 靜態庫適合小型工具、動態庫適合模組化部署,掌握 __declspec 與 extern "C" 關鍵字
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved