簡體   English   中英

C ++標准在哪里說,C在哪里說相同:編譯單元(.cpp文件)中的變量按聲明順序初始化

[英]Where does the C++ standard say, and does C say the same: variables in a compilation unit (.cpp file) are initialised in order of declaration

是說

C ++保證按聲明順序初始化編譯單元(.cpp文件)中的變量

對於C同樣嗎?

您可以引用C和C ++的相關標准段落嗎?

讓我們從C開始。向C詢問就像是在問:如果一棵樹掉在森林里,沒人在周圍聽到它,它會發出聲音嗎? 沒關系,因為沒有任何方法可以編寫有效的C程序來說明差異。 這意味着標准對此沒有意義。 我們需要知道的是,到任何代碼運行時,具有靜態存儲持續時間的變量都已初始化。 C11標准草案在5.1.2節中進行了詳細說明:

程序啟動前,所有具有靜態存儲持續時間的對象都應初始化(設置為其初始值)。 否則未指定這種初始化的方式和時間。

另一方面,在C ++中,事情並非那么簡單。 在動態初始化期間可以觀察初始化的順序。 標准草案中,我們找到了3.6.2節。 它很快變得復雜。 它將順序定義為:首先我們進行靜態初始化(這等效於C可以做的唯一事情),然后完成動態初始化。 到現在為止還挺好。 我們到這一部分:

在單個轉換單元中定義了有序初始化的變量,應按其在轉換單元中定義的順序進行初始化。

而且世界上一切都還好。 但是事情很快就崩潰了:

允許實現以靜態存儲持續時間執行非局部變量的初始化作為靜態初始化,即使這種初始化不需要以靜態方式完成

這句話使我們從一個可以預見的世界轉向“它很復雜”。 標准的該部分中的代碼示例對此進行了完美解釋:

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1;   // unspecified:
                  // may be statically initialized to 0.0 or
                  // dynamically initialized to 0.0 if d1 is
                  // dynamically initialized, or 1.0 otherwise
double d1 = fd(); // may be initialized statically or dynamically to 1.0

簡而言之,在C語言中沒關系,在C ++中,如果編寫依賴於此的代碼,則在更改編譯器時很可能會遇到麻煩。

因此,您的報價是雙重錯誤的。 初始化不僅沒有按照聲明的順序進行(先是靜態,然后是動態),而且實際上是靜態的還是動態的也很模糊。

在C ++中,必須定義初始化的順序,因為可能存在在變量的初始化中調用的構造函數。 因此,C ++定義了此代碼的執行順序。 在普通C中,沒有構造函數。 只要在執行任何可以訪問該變量的代碼之前就初始化每個變量,就無法確定變量的初始化順序。

C標准(C11)6.7.6說

完整聲明符是不屬於另一個聲明符的聲明符。 完整聲明符的末尾是一個序列點。

這意味着在每個聲明的末尾,必須完成初始化並且必須對所有子表達式進行副作用評估。

未指定實際代碼的執行時間。 這意味着可以在進行初始化的行之前很長時間完成,但不能在該行之后完成。

具有靜態存儲持續時間的變量是一種特殊情況,因為可以保證在程序啟動之前對其進行初始化。 它們的執行順序在C語言中無關緊要,因為它們彼此不依賴(必須初始化為常量表達式)。

在C ++中,具有靜態存儲持續時間的類對象以未指定的順序初始化,因此不應編寫它們,以便它們彼此依賴以特定的順序進行初始化。

另請注意6.7.9 / 23:

初始化列表表達式的求值相對於彼此不確定地排序,因此未指定發生任何副作用的順序。

這意味着我們不知道執行同一聲明的所有初始化程序部分的順序。

我相信C和C ++在上述所有方面都是相同的,盡管C ++還將在初始化過程中執行構造函數。

暫無
暫無

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

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