C++獲取對象真實地址的方法
問題背景
在 C++ 中,當(dāng)類重載了 operator& 時,直接使用 & 運算符無法獲取對象的真實內(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,不是真實地址!
}
解決方案對比
方法對比表
| 方法 | 適用標(biāo)準(zhǔn) | 可靠性 | 可讀性 | 推薦度 |
|---|---|---|---|---|
| std::addressof | C++11+ | ????? | ????? | ????? |
| 類型轉(zhuǎn)換技巧 | C++98+ | ???? | ?? | ??? |
技術(shù)原理剖析
1. std::addressof 實現(xiàn)原理
標(biāo)準(zhǔn)庫實現(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)存布局可視化
對象內(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ù) (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 << "=== 錯誤方法 ===\n";
std::cout << "&obj: " << &obj << " (錯誤地址!)\n";
std::cout << "&const_obj: " << &const_obj << " (錯誤地址!)\n\n";
std::cout << "=== 正確方法 ===\n";
// 使用 std::addressof (C++11)
std::cout << "std::addressof(obj): " << std::addressof(obj) << " (真實地址)\n";
std::cout << "std::addressof(const_obj): " << std::addressof(const_obj) << " (真實地址)\n\n";
// 使用類型轉(zhuǎn)換技巧 (C++98 兼容)
std::cout << "get_real_address(obj): " << get_real_address(obj) << " (真實地址)\n";
std::cout << "get_real_address(const_obj): " << get_real_address(const_obj) << " (真實地址)\n";
// 驗證地址真實性
std::cout << "\n=== 驗證 ===\n";
std::cout << "obj.data: " << obj.data << " (通過真實地址訪問: ";
std::cout << std::addressof(obj)->data << ")\n";
return 0;
}
編譯與運行
# 編譯 (需要支持 C++11) g++ -std=c++11 -o example example.cpp # 運行 ./example
預(yù)期輸出
=== 錯誤方法 === 重載的 operator& 被調(diào)用 &obj: 0xdeadbeef (錯誤地址!) const 重載的 operator& 被調(diào)用 &const_obj: 0xdeadbeef (錯誤地址!) === 正確方法 === std::addressof(obj): 0x7ffd108a1b5c (真實地址) std::addressof(const_obj): 0x7ffd108a1b60 (真實地址) get_real_address(obj): 0x7ffd108a1b5c (真實地址) get_real_address(const_obj): 0x7ffd108a1b60 (真實地址) === 驗證 === obj.data: 42 (通過真實地址訪問: 42)
關(guān)鍵總結(jié)
- 問題本質(zhì):
operator&重載改變了&運算符的默認(rèn)行為 - 解決方案:
- ? C++11+:優(yōu)先使用
std::addressof - ? C++98:使用類型轉(zhuǎn)換技巧
- ? C++11+:優(yōu)先使用
- 適用場景:
- 底層內(nèi)存操作和調(diào)試
- 與 C 語言庫交互
- 序列化和反序列化操作
- 注意事項:
- 類型轉(zhuǎn)換技巧在極端情況下可能受對齊影響
std::addressof是標(biāo)準(zhǔn)庫實現(xiàn),更加可靠
建議:在新項目中始終使用 std::addressof,在維護(hù)舊代碼時根據(jù)需要選擇合適方法。
以上就是C++獲取對象真實地址的方法的詳細(xì)內(nèi)容,更多關(guān)于C++獲取對象真實地址的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++深入詳解單例模式與特殊類設(shè)計的實現(xiàn)
這篇文章主要為大家詳細(xì)介紹了C++單例模式和特殊類的設(shè)計,單例模式這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-06-06
C語言實現(xiàn)學(xué)生選修課程系統(tǒng)設(shè)計
這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)學(xué)生選修課程系統(tǒng)設(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-02-02
C++11新特性之右值引用與完美轉(zhuǎn)發(fā)詳解
C++11標(biāo)準(zhǔn)為C++引入右值引用語法的同時,還解決了一個短板,即使用簡單的方式即可在函數(shù)模板中實現(xiàn)參數(shù)的完美轉(zhuǎn)發(fā)。本文就來講講二者的應(yīng)用,需要的可以參考一下2022-09-09
C++?MiniZip實現(xiàn)目錄壓縮與解壓的示例詳解
Zlib是一個開源的數(shù)據(jù)壓縮庫,提供了一種通用的數(shù)據(jù)壓縮和解壓縮算法,本文主要為大家詳細(xì)介紹了如何利用Zlib實現(xiàn)目錄壓縮與解壓,需要的小伙伴可以參考下2023-11-11

