2011-05-31 204 views
19

int foo = foo;編譯。 C++標準的哪一部分允許這樣做?int foo = foo的標準參考

+0

相關:http://stackoverflow.com/questions/5450633/c-what-does-this-mean-int-foo-foo-4 – 2011-05-31 17:47:04

+0

另請參閱[初始化是否需要左值到右值的轉換?是'INT X = X;'UB](http://stackoverflow.com/q/14935722/1708801)和[已C++標準相對於在C++ 14使用不定值和未定義的行爲的改變]? (http://stackoverflow.com/q/23415661/1708801) – 2015-09-22 15:27:16

回答

26

3.3.1點聲明[basic.scope.pdecl]

聲明的一個名字的一點是後立即其完整說明符(第8節)和它的初始值設定前(如果有的話),

的行爲,如果該聲明是在文件範圍是明確界定。如果你有在申報範圍的功能,如果你使用foo稍後[這將被初始化爲在這種情況下一些未指定值]的行爲將是不確定的。

+4

我會+1,但你完全沒有提到OP的程序有未定義的行爲,並且不能使用_。 – 2011-05-31 14:40:47

+5

@Tomalak:代碼*可能*有UB,但不一定。 OP似乎完全意識到這不是真的應該使用的東西,並且對它爲什麼編譯的純學術觀點感到好奇。 – 2011-05-31 14:43:18

+2

@Jerry:仙女nuff。 – 2011-05-31 14:44:47

21

This?

int main() { 
    int foo = foo; 
} 

目的foo=後確實存在,根據[basic.scope.pdecl]

聲明的一個名字的一點是後立即其完整說明符(第8節)和其初始值設定前(如果有的話)。

然而,該方案整體上是不確定的,因爲你使用(在RHS)的未初始化值:

int x = x; 這裏[..] x與自己的(不確定)初始化值。

和:

雖然 「推斷和虐待的規定」 的標準,an lvalue-to-rvalue conversion is performed on the RHS expression foo

和([conv.lval]):

非函數的左值(3.10), 非陣列類型T可以被轉換爲 右值。如果T是不完整的類型, 需要此 轉換的程序是不合格的。如果 對象到的左值是指是 不類型T的對象,而不是源自T的類型的 對象,或者如果 對象是未初始化,即必要這種轉換的程序 具有 未定義的行爲。

具有適當的警告級別,you will get told about it;但是,允許編譯調用未定義行爲的程序。當你運行它們時,它們可以做任何事情。


或者,這個怎麼樣?

int foo = foo;  
int main() {} 

請注意foo是一個「全局」。這些是零初始化作爲第一步,根據[basic.start.init]

具有靜態存儲的持續時間(3.7.1)的對象應是零初始化(8.5)任何其它初始化發生之前。

因此,您將得到一個值爲0的int foo;它是有效的,在這一點上,按照[basic.scope.pdecl]上方,並且每[stmt.decl]爲:

具有靜態存儲 持續時間所有 本地對象的零初始化(8.5)(3.7.1)的任何 之前執行其他初始化發生。 [..]

你那麼如果有點神祕值初始化到foo(本身),即0。

這是良好定義...。


在徹底的利益,這裏的第三和最後一種情況:

int foo = 42; 
int main() { 
    int foo = foo; 
} 

可悲的是,this is the same as the first case。由於本地foo已經宣佈在由初始評估的時間範圍,初始化使用本地foo和你仍然堅持與未定義行爲。全局foo未使用。

+1

OTOH,如果它是一個全球性的,行爲定義。 – 2011-05-31 14:41:41

+0

@Jerry:我的程序中沒有全局變量。如果OP程序中有全局變量(或者他的'foo'聲明發生在命名空間範圍內),他需要說明這一點,因爲它完全改變了問題。 – 2011-05-31 14:42:51

+0

@Jerry:好的。那麼我也會爲這種情況添加一個條款。 – 2011-05-31 14:46:23

相關問題