C++獲取對(duì)象真實(shí)地址的方法
問題背景
在 C++ 中,當(dāng)類重載了 operator& 時(shí),直接使用 & 運(yùn)算符無法獲取對(duì)象的真實(shí)內(nèi)存地址,而是調(diào)用重載函數(shù)返回自定義值。
class TrickyClass {
public:
int data;
// 重載的 operator& 返回假地址
TrickyClass* operator&() {
return reinterpret_cast<TrickyClass*>(0xDEADBEEF);
}
};
int main() {
TrickyClass obj;
TrickyClass* addr = &obj; // 返回 0xDEADBEEF,不是真實(shí)地址!
}
解決方案對(duì)比
方法對(duì)比表
| 方法 | 適用標(biāo)準(zhǔn) | 可靠性 | 可讀性 | 推薦度 |
|---|---|---|---|---|
| std::addressof | C++11+ | ????? | ????? | ????? |
| 類型轉(zhuǎn)換技巧 | C++98+ | ???? | ?? | ??? |
技術(shù)原理剖析
1. std::addressof 實(shí)現(xiàn)原理
標(biāo)準(zhǔn)庫實(shí)現(xiàn)通常如下:
template<typename T>
T* addressof(T& arg) noexcept {
return reinterpret_cast<T*>(
&const_cast<char&>(
reinterpret_cast<const volatile char&>(arg)
)
);
}
2. 類型轉(zhuǎn)換技巧解析

內(nèi)存布局可視化
對(duì)象內(nèi)存布局與地址獲取

決策流程圖

完整示例代碼
#include <iostream>
#include <memory> // 用于 std::addressof
// 重載了 operator& 的示例類
class TrickyClass {
public:
int data{42};
// 重載的 operator& 返回假地址
TrickyClass* operator&() {
std::cout << "重載的 operator& 被調(diào)用\n";
return reinterpret_cast<TrickyClass*>(0xDEADBEEF);
}
// const 版本的重載
const TrickyClass* operator&() const {
std::cout << "const 重載的 operator& 被調(diào)用\n";
return reinterpret_cast<const TrickyClass*>(0xDEADBEEF);
}
};
// 獲取真實(shí)地址的通用函數(shù) (C++98 兼容)
template <typename T>
T* get_real_address(T& obj) {
return reinterpret_cast<T*>(
&const_cast<char&>(
reinterpret_cast<const volatile char&>(obj)
)
);
}
int main() {
TrickyClass obj;
const TrickyClass const_obj;
std::cout << "=== 錯(cuò)誤方法 ===\n";
std::cout << "&obj: " << &obj << " (錯(cuò)誤地址!)\n";
std::cout << "&const_obj: " << &const_obj << " (錯(cuò)誤地址!)\n\n";
std::cout << "=== 正確方法 ===\n";
// 使用 std::addressof (C++11)
std::cout << "std::addressof(obj): " << std::addressof(obj) << " (真實(shí)地址)\n";
std::cout << "std::addressof(const_obj): " << std::addressof(const_obj) << " (真實(shí)地址)\n\n";
// 使用類型轉(zhuǎn)換技巧 (C++98 兼容)
std::cout << "get_real_address(obj): " << get_real_address(obj) << " (真實(shí)地址)\n";
std::cout << "get_real_address(const_obj): " << get_real_address(const_obj) << " (真實(shí)地址)\n";
// 驗(yàn)證地址真實(shí)性
std::cout << "\n=== 驗(yàn)證 ===\n";
std::cout << "obj.data: " << obj.data << " (通過真實(shí)地址訪問: ";
std::cout << std::addressof(obj)->data << ")\n";
return 0;
}
編譯與運(yùn)行
# 編譯 (需要支持 C++11) g++ -std=c++11 -o example example.cpp # 運(yùn)行 ./example
預(yù)期輸出
=== 錯(cuò)誤方法 === 重載的 operator& 被調(diào)用 &obj: 0xdeadbeef (錯(cuò)誤地址!) const 重載的 operator& 被調(diào)用 &const_obj: 0xdeadbeef (錯(cuò)誤地址!) === 正確方法 === std::addressof(obj): 0x7ffd108a1b5c (真實(shí)地址) std::addressof(const_obj): 0x7ffd108a1b60 (真實(shí)地址) get_real_address(obj): 0x7ffd108a1b5c (真實(shí)地址) get_real_address(const_obj): 0x7ffd108a1b60 (真實(shí)地址) === 驗(yàn)證 === obj.data: 42 (通過真實(shí)地址訪問: 42)
關(guān)鍵總結(jié)
- 問題本質(zhì):
operator&重載改變了&運(yùn)算符的默認(rèn)行為 - 解決方案:
- ? C++11+:優(yōu)先使用
std::addressof - ? C++98:使用類型轉(zhuǎn)換技巧
- ? C++11+:優(yōu)先使用
- 適用場(chǎng)景:
- 底層內(nèi)存操作和調(diào)試
- 與 C 語言庫交互
- 序列化和反序列化操作
- 注意事項(xiàng):
- 類型轉(zhuǎn)換技巧在極端情況下可能受對(duì)齊影響
std::addressof是標(biāo)準(zhǔn)庫實(shí)現(xiàn),更加可靠
建議:在新項(xiàng)目中始終使用 std::addressof,在維護(hù)舊代碼時(shí)根據(jù)需要選擇合適方法。
以上就是C++獲取對(duì)象真實(shí)地址的方法的詳細(xì)內(nèi)容,更多關(guān)于C++獲取對(duì)象真實(shí)地址的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解C++的String類的字符串分割實(shí)現(xiàn)
這篇文章主要介紹了詳解C++的String類的字符串分割實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-07-07
C語言簡明分析選擇結(jié)構(gòu)和循環(huán)結(jié)構(gòu)的使用
C語言條件控制語句選擇結(jié)構(gòu),是屬于計(jì)算機(jī)的語言編輯,有在C語言條件控制中的語句選擇結(jié)構(gòu)的存在,即是C語言條件控制語句選擇結(jié)構(gòu),循環(huán)控制語句是一個(gè)基于C語言的編程語句,該語句主要有while循環(huán)語句、do-while循環(huán)語句和for循環(huán)語句來實(shí)現(xiàn)循環(huán)結(jié)構(gòu)2022-04-04
C++實(shí)現(xiàn)學(xué)生管理系統(tǒng)示例解析
這篇文章主要介紹了C++實(shí)現(xiàn)學(xué)生管理系統(tǒng)示例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
這篇文章主要介紹了C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例,并且轉(zhuǎn)換后會(huì)統(tǒng)計(jì)二進(jìn)制1的個(gè)數(shù),實(shí)例簡單明了,需要的朋友可以參考下2014-06-06

