《C++ Primer》第 5 版 P50 指出:一個指針指向某對象,另一個指針指向「另一對象的下一地址」,此時兩指針可能相等。這看似矛盾實則揭示了 C++ 對象模型與指針算術的深層邏輯。本文通過內存佈局圖解徹底講透。
「另一對象」與「某對象」在內存中恰好相鄰,且「另一對象」緊挨在「某對象」之前。此時「另一對象的下一地址」即「某對象的起始地址」,兩指針值相等。
假設對象 A (int, 4字節) 與 對象 B (int, 4字節) 在棧上相鄰分配,B 在低地址,A 在高地址:
地址: 0x1000 0x1004 0x1008
+--------+--------+
| B | A | ← 內存佈局(棧向下增長時反過來,邏輯相同)
+--------+--------+
↑
指針 p1 = &A; // 指向「某對象」A 的起始地址 0x1004
指針 p2 = &B + 1; // 指向「另一對象」B 的「下一地址」= 0x1000 + sizeof(B) = 0x1004
結果:p1 == p2 為 true
ptr + n 表示向後偏移 n * sizeof(T) 字節。&B + 1 指向緊隨 B 之後的 T 類型對象位置(即「下一個」假想對象的起始地址)。std::addressof 獲取地址,用 std::uintptr_t 比較數值,或重新設計數據結構(如用數組/結構體確保佈局)。int arr[3] = {1,2,3};
int *p1 = &arr[2]; // 指向最後一個元素
int *p2 = arr + 3; // 一過去尾指針
// p1 + 1 == p2 為 true
// *p2 是 UB!
理解此邊界情況,有助於深入掌握 C++ 指針語義、迭代器失效規則及標準庫算法(如 std::sort(begin, end) 中 end 即一過去尾)的設計哲學。