std::addressof
模板函式定義在標頭檔案中,用於獲取類或函式的真實位址,即使在類過載了位址操作符&的情況下也能正常工作。它有如下三個宣告:
template
<
typename t>
t*addressof
(t& arg)
noexcept
;// (1) 從c++11開始支援
template
<
typename t>
constexpr t*
addressof
(t &arg)
noexcept
;// (2) 從c++17開始支援
template
<
class
t>
const t*
addressof
(const t&&)=
delete
;// (3) 從c++17開始支援
其中arg必須是乙個左值物件或者函式。從c++17開始,在arg
是乙個左值常量表示式時,addressof
也保證是乙個常量表示式。常量表示式是指在編譯時就能獲得結果的表示式。宣告(3)的目的是為了阻止獲取常量右值的位址。
以下原始碼分析基於gcc 9.2.0和llvm clang 9.0.1。
/* gcc */
template
<
typename t>
inline
constexpr t*
__addressof
(t& arg)
noexcept
/* clang */
#ifndef _libcpp_has_no_builtin_addressof
template
<
class
t>
inline
constexpr t*
addressof
(t& arg)
noexcept
#else
template
<
class
t>
inline t*
addressof
(t& arg)
noexcept
#endif
// _libcpp_has_no_builtin_addressof
從實現來看,gcc和clang有些許不同。
當存在內建函式__builtin_addressof
時,clang和gcc實現一樣,使用內建函式__builtin_addressof
來獲取引數arg
的位址。
當不存在內建函式__builtin_addressof
時,clang使用reinterpret_cast
和const_cast
組合來獲取arg
的位址。為什麼要用這麼複雜的表示式來獲取位址,而不使用&arg
來獲取位址呢?因為arg
有可能是乙個過載了位址操作符&的類,那麼&arg
就不再是取位址的語義了。
那__builtin_addressof
和reinterpret_cast
組合又有什麼不同呢?最大的不同在於__builtin_addressof
是乙個常量表示式,在編譯時就能獲得表示式的值,而reinterpret_cast
組合不是常量表示式。
在c++常量表示式的定義中,其中一條要求就是「常量表示式中不能有reinterpret_cast
表示式」,此要求可以通過如下**進行驗證。
constexpr
int*to(
char
*p)
使用gcc編譯會提示錯誤「a reinterpret_cast is not a constant expression」,而使用clang編譯會提示錯誤「constexpr function never produces a constant expression [-winvalid-constexpr]」,這些錯誤都說明了reinterpret_cast
不能產生常量表示式,也就是在有些情況下,它需要在執行時求解表示式的值。 Activity Intent深入解析
學習android sdk有段時間了,對activity intent的學習與使用都比較了解。第一次完整的學習activity intent後,我就感覺這似乎與windows com技術有些似曾相識的感覺,寫了一篇將activity 與 com 做了比較,但是一直感覺意猶未盡,前幾天在程式設計師雜誌...
深入解析IOCP
1.介紹 1.1 高併發伺服器 1 要求大規模的連線 會話可能同時進行 2 列子 web 伺服器,郵件伺服器 1.2 執行緒池架構 1 每個連線分配乙個執行緒,將導致過多的執行緒。2 執行緒消耗記憶體,比如堆疊等等。2.執行緒模型 2.1 基於會話模型 1 每個執行緒服務於乙個客戶端,比如http ...
HTTP 深入解析
1.cookie 儲存在客戶端 cookie 的類別 cookie 的屬性 了解 cookie 的應用場景 同源http請求 攜帶cookie 原生ajax請求方式 xhr.withcredentials true 支援跨域傳送cookies xhr.send jquery的ajax的post方法請...