C++獲取對(duì)象真實(shí)地址的方法
問(wèn)題背景
在 C++ 中,當(dāng)類重載了 operator& 時(shí),直接使用 & 運(yùn)算符無(wú)法獲取對(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)庫(kù)實(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 << " (通過(guò)真實(shí)地址訪問(wèn): ";
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 (通過(guò)真實(shí)地址訪問(wèn): 42)
關(guān)鍵總結(jié)
- 問(wèn)題本質(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 語(yǔ)言庫(kù)交互
- 序列化和反序列化操作
- 注意事項(xiàng):
- 類型轉(zhuǎn)換技巧在極端情況下可能受對(duì)齊影響
std::addressof是標(biāo)準(zhǔn)庫(kù)實(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++深入詳解單例模式與特殊類設(shè)計(jì)的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了C++單例模式和特殊類的設(shè)計(jì),單例模式這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-06-06
C語(yǔ)言實(shí)現(xiàn)學(xué)生選修課程系統(tǒng)設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生選修課程系統(tǒng)設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
C++11新特性之右值引用與完美轉(zhuǎn)發(fā)詳解
C++11標(biāo)準(zhǔn)為C++引入右值引用語(yǔ)法的同時(shí),還解決了一個(gè)短板,即使用簡(jiǎn)單的方式即可在函數(shù)模板中實(shí)現(xiàn)參數(shù)的完美轉(zhuǎn)發(fā)。本文就來(lái)講講二者的應(yīng)用,需要的可以參考一下2022-09-09
FFmpeg實(shí)現(xiàn)多線程編碼并保存mp4文件
這篇文章主要為大家介紹了FFmpeg如何持續(xù)的從指定內(nèi)存中讀取原始數(shù)據(jù),再將解碼數(shù)據(jù)存入隊(duì)列中,并通過(guò)單獨(dú)的線程進(jìn)行編碼,最后保存為mp4文件,感興趣的可以了解下2023-08-08
C++?MiniZip實(shí)現(xiàn)目錄壓縮與解壓的示例詳解
Zlib是一個(gè)開(kāi)源的數(shù)據(jù)壓縮庫(kù),提供了一種通用的數(shù)據(jù)壓縮和解壓縮算法,本文主要為大家詳細(xì)介紹了如何利用Zlib實(shí)現(xiàn)目錄壓縮與解壓,需要的小伙伴可以參考下2023-11-11

