2010-11-02 33 views
6

C++ 0x draft爲什麼要求將全局匿名工會聲明爲靜態?

9.5.6在一個名爲命名空間或在全局命名空間中聲明匿名工會應被宣佈爲靜態的。

爲什麼?


更新 -

基於巴特麪包車不收Schenau和洛薩的階躍響應,最好的解釋,到目前爲止可能是這樣的:

如果相同的全局匿名聯合在兩個翻譯單元遇到的(比方說,通過頭文件),那麼如何滿足一個定義規則呢?這兩個定義是否被視爲相同併合並在一起?或者這兩種定義被視爲不同?如果他們被視爲相同,那麼編譯器大概會做'魔術',否則它不會爲其他實體做。如果它們被視爲相同,那麼編譯器在沒有程序員的明確同意的情況下這樣做......所以我想明確的同意是被迫聲明爲靜態的。

回答

1

我的猜測是,如果允許在非靜態的方式來定義工會,否則可能違反了不需要ODR (one definition rule)

+0

這加上Bart van Ingen Schenau的迴應可能是迄今爲止最好的解釋。 – Vatsan 2010-11-02 16:25:24

1

我最好的猜測:

如果它是非靜態的,也可能被其他代碼引用。但其他代碼會怎麼稱呼它?它是匿名的。因此,需要將匿名聯合限制在某個本地範圍內;因此,它應被宣佈爲靜態。

但它只是一個猜測。語言設計師可以按照他們想要的方式設計事物。有時他們的選擇是隨意的,只是因爲一些必須作出選擇。

+0

我不明白它在代碼的不同部分被稱爲什麼可能是問題 - 因爲它不被稱爲任何東西。相反,只有成員被直接引用,並且他們都有名字。這是聯盟本身,而不是其成員。 – Vatsan 2010-11-02 03:11:19

+0

我想我想知道爲什麼這個功能是按照它的方式設計的。順便說一下,這種行爲並不是新的C++ 0x(儘管我引用了C++ 0x草案) - 現在已經有一段時間了。 – Vatsan 2010-11-02 03:14:35

0

$ 9.5/5-形式聯合的聯合成員規範}被稱爲 匿名聯盟; 它定義了一個未命名類型的未命名對象

我猜它應該是靜態的,以便對象可以根據全局靜態對象的規則進行初始化。如果它不是靜態的,並且對象沒有名稱,那麼如何初始化它?

EDIT2:

重新思考...匿名工會

成員有內部鏈接。此外,默認情況下全球名稱具有外部鏈接,除非它們具有內部鏈接如果匿名工會的名稱有外部鏈接,則匿名工會的成員不可能有內部鏈接。因此匿名聯合使用「靜態」存儲類說明符聲明,以便匿名名稱本身具有內部鏈接。

+0

該死的!我不知道如何擺脫雙'定義' – Chubsdad 2010-11-02 03:56:08

+0

使它靜態將提供'零初始化'。但爲什麼默認(零)初始化需要呢?它的成員可以通過他們的名字來引用,所以第一次爲anon-union的成員分配一個值時,anon-union將被初始化。我錯過了什麼? – Vatsan 2010-11-02 04:09:52

+0

@Vatsan Madhavan:任務與初始化不同 – Chubsdad 2010-11-02 04:12:06

4

假設匿名聯合中聲明靜態的,編譯器遇到這兩個翻譯單位(後預處理):

File1中:

union { 
    int a; 
    char b; 
}; 

// Further contents referring to a and b 

文件2:

union { 
    int a; 
    char b; 
}; 

// Further (different) contents referring to a and b 

這兩個工會是一個相同的對象,還是他們應該是不同的對象?

我認爲,爲了避免像這樣無法回答的問題,已經決定命名空間範圍的匿名聯合必須聲明爲靜態的。

+0

我認爲這個結合lothar的ODR反應可能是迄今爲止最好的解釋。 – Vatsan 2010-11-02 16:20:56

-1

從來沒有理由爲靜態要求,它應該被刪除。編譯器確實並應該將聯合中的多個元素視爲共享相同地址的多個單獨全局變量。實際上,這意味着編譯器允許將多種類型應用於相同的地址。由於全局匿名聯合的範圍是全局範圍,所以匿名聯合中的元素命名規則應該(和)與命名全局變量的規則相同。即匿名聯合元素名稱必須是唯一的。至於union的初始化 - 聯合的初始化和簡單變量的初始化沒有區別。關於靜態聯合的另一點 - 聯合的價值和類型是時間依賴的。請注意,無論其中的元素數量如何,一次只能有一個值佔用聯合。聲明聯合開始的原因是允許在不同時間動態地將不同類型的地址用於不同類型的地址。這就是爲什麼一個靜態工會是一個誤稱,一些編譯器會忽略它。

相關問題