C++ 中指針的高級應用非常豐富,掌握這些內容能讓你寫出更高性能、更底層控制力強的代碼。下面是應用模塊梳理和例子講解。
目錄預覽
- 函數指針與回調機制
- 指針數組 vs 數組指針
- 指針與類成員函數(成員函數指針)
- 智能指針(
unique_ptr
,shared_ptr
,weak_ptr
) - 指針與繼承、虛函數表(vtable)
- 指針與內存對齊、指針算術
- 指針類型轉換(
reinterpret_cast
,static_cast
) - 指針模擬多態和接口
- 自定義 allocator / 內存池(高級性能優化)
- 指針與并發(原子指針、鎖自由結構)
1. 函數指針與回調機制
聲明與使用
void hello() {std::cout << "Hello\n";
}void call(void (*func)()) {func(); // 調用傳入的函數指針
}
也可以傳入帶參數的函數:
void print(int x) {std::cout << x << "\n";
}void call(void (*func)(int), int val) {func(val);
}
2. 指針數組 vs 數組指針
表達式 | 含義 |
---|---|
int* arr[10] | 數組,每個元素是 int* |
int (*arr)[10] | 指向數組 的指針 |
示例
int* pArr[10]; // 10 個 int 指針
int arr[10];
int (*p)[10] = &arr; // 一個指針,指向包含 10 個 int 的數組
3. 成員函數指針
聲明和調用成員函數指針:
class A {
public:void show() { std::cout << "A::show\n"; }
};void (A::*pFunc)() = &A::show;A a;
(a.*pFunc)(); // 使用成員函數指針調用
注意:成員函數指針與普通函數指針不同,它需要對象實例才能調用。
4. 智能指針(現代 C++ 的推薦方式)
std::unique_ptr
std::unique_ptr<int> p = std::make_unique<int>(10);
- 不能拷貝,只能轉移
- 自動析構,無需手動 delete
std::shared_ptr
std::shared_ptr<int> p1 = std::make_shared<int>(20);
std::shared_ptr<int> p2 = p1; // 引用計數 +1
- 多個指針共享對象生命周期
std::weak_ptr
避免循環引用
std::weak_ptr<int> wp = p1;
5. 指針與虛函數表(vtable)
基類指針指向派生類(多態)
class Base {
public:virtual void foo() { std::cout << "Base\n"; }
};class Derived : public Base {
public:void foo() override { std::cout << "Derived\n"; }
};Base* b = new Derived();
b->foo(); // 輸出 "Derived"
底層通過虛函數表(vtable)實現,vptr 指針指向類的虛函數表。
6. 內存對齊與指針算術
struct alignas(16) Vec4 {float x, y, z, w;
};
指針算術是按類型大小偏移的:
int* p = arr;
p += 2; // 實際偏移 sizeof(int) * 2 字節
7. 指針類型轉換
int a = 10;
void* vp = &a;int* ip = static_cast<int*>(vp); // OK
float* fp = reinterpret_cast<float*>(ip); // 危險,類型錯配
類型轉換建議順序:
static_cast
:安全的編譯期轉換reinterpret_cast
:位級別轉換,需小心const_cast
:去掉const
限定dynamic_cast
:用于 RTTI 下的多態類型轉換(帶virtual
)
8. 指針模擬多態與接口
struct Interface {void (*run)(void*);void* self;
};void do_something(void* p) {std::cout << "Run on raw object\n";
}Interface iface = { do_something, nullptr };
iface.run(iface.self);
- 類似于 C 風格接口表
- 可用于插件系統、自定義腳本語言嵌入等
9. 自定義內存分配器(性能優化)
使用自定義 pointer allocator,跳過 malloc/new:
template <typename T>
class MyAllocator {...T* allocate(size_t n) { return static_cast<T*>(::operator new(n * sizeof(T))); }
};
結合 STL 使用:
std::vector<int, MyAllocator<int>> v;
也可做內存池管理(如用于點云、游戲對象池)
10. 指針與并發
std::atomic<T*>
保證多線程訪問安全- 可用于 lock-free 數據結構
std::atomic<int*> ap;
int* p = new int(42);
ap.store(p);
高級:Hazard Pointer、ABA 問題、Compare-And-Swap(CAS)
總結腦圖式表
┌────────────┐│ 高級指針用法│└────────────┘↓┌────────────┬────────────┬────────────┬────────────┐│ 函數指針 │ 成員指針 │ 智能指針 │ 指針算術 │├────────────┴────────────┴────────────┴────────────┤│ 內存池 │ 指針與類 │ vtable 多態│ 類型轉換 │├────────────┬────────────┬────────────┬────────────┤│ ABI + 棧幀 │ 并發原子指針│ 插件接口 │ STL allocator │└────────────┴────────────┴────────────┴────────────┘