簡體   English   中英

如何在標頭中使用未命名的命名空間會導致ODR違規?

[英]How would use of unnamed namespaces in headers cause ODR-violations?

在Google C ++樣式指南中, 命名空間部分指出“ 在頭文件中使用未命名的命名空間很容易導致違反C ++ One Definition Rule(ODR)。

我理解為什么不在實現文件中使用未命名的命名空間可能會導致ODR違規,但不能在標頭中使用它們。 這怎么會導致違規?

原因是,如果您實際使用匿名命名空間中的任何內容,則存在未定義行為的風險。 例如:

namespace {
double const pi = 3.14159;
}

inline double twoPiR( double r ) { return 2.0 * pi * r; }

內聯函數(以及類和模板以及必須在多個翻譯單元中定義的任何其他內容)的規則是令牌必須相同(通常情況下,除非您點擊某個宏),並且所有符號必須相同地綁定。 在這種情況下,每個翻譯單元具有單獨的pi實例,因此兩個twoPiRpi綁定到每個翻譯單元中的不同實體。 (有一些例外,但它們都涉及整體表達。)

當然,即使沒有匿名命名空間,這也是未定義的行為(因為const默認意味着內部鏈接),但基本原則成立。 在未命名的命名空間(或標頭中定義的任何const對象)中的任何內容的標頭中的任何使用都可能導致未定義的行為。 它是否是一個真正的問題取決於,但肯定涉及上述pi的地址的任何事情都會引起問題。 (我在這里說“真的”,因為很多情況下地址或引用都是正式使用的,但實際上,內聯擴展會導致實際使用的值。當然,令牌3.141593.14159而不管它出現的地方。)

在test.h中

namespace {
  int x;
}

namespace{
  int x;
}

在任何源文件中包含該頭文件都會導致ODR違規,因為x被定義了兩次。 發生這種情況是因為編譯器為未命名的命名空間賦予了唯一標識符,並且翻譯單元中所有出現的未命名命名空間都被賦予相同的標識符。 換句話說:每個TU最多只有一個未命名的命名空間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM