[英]Scope vs. Lifetime of Variable
變量的作用域和生命周期之間有什么關系? 如果一個變量超出范圍,它的內存是否允許被另一個變量覆蓋,或者是否保留空間直到函數離開。
我在 aksing 因為我想知道下面的代碼是否真的有效,或者 *p 是否可能是未定義的
foo() {
int *p;
{
int x = 5;
p = &x;
}
int y = *p;
}
什么是范圍?
范圍是可以訪問變量的區域或代碼段。
什么是一生?
生命周期是對象/變量處於有效狀態的持續時間。
對於,自動/本地非靜態變量Lifetime
僅限於它們的Scope
。
換句話說,一旦創建它們的作用域( {
, }
)結束,自動變量就會自動銷毀。 因此,名稱自動開始。
您的代碼示例有什么問題?
所以是的,你的代碼有一個Undefined Behavior 。
在您的示例中, *p
范圍是創建后的整個函數體。
然而, x
是一個非靜態局部/自動變量,因此x
的生命周期以其作用域結束,即創建它的}
的右大括號,一旦作用域結束x
就不存在。 *p
指向不再存在的東西。
請注意,技術上x
不存在於其范圍之外,但是可能會發生編譯器沒有刪除x
的內容,並且一個人可能能夠通過指針訪問超出其范圍的x
內容(就像您所做的那樣)。但是,代碼這不是有效的 C++ 代碼。 這是一個調用未定義行為的代碼。 這意味着任何事情都可能發生(您甚至可能會看到x
值是完整的),並且不應期望從這樣的代碼中可以觀察到行為。
對於標識符指定的每個不同實體,標識符僅在稱為其范圍的程序文本區域內可見(即,可以使用)。 由同一標識符指定的不同實體要么具有不同的作用域,要么位於不同的名稱空間中
.
對象的生命周期是程序執行的一部分,在此期間保證為其保留存儲空間。
在你的情況下, x
是塊的本地,它的生命周期也是如此,因此x
不能在塊外通過它的名字訪問,也因為它的生命周期僅限於它的塊,離開塊后x
的地址將不再保留,因此將導致未定義的行為。
另一方面,例如,說一個static
局部變量,在這種情況下,作用域是塊本地的,所以我們不能在塊外通過它的名字訪問,但生命周期是整個程序,所以我們可以使用程序運行時變量在程序中任何位置的地址。 這個例子應該有助於區分。
對象(即存儲值的實際底層事物)具有生命周期。
變量(即用來指代對象的東西)有作用域。
無論哪種方式, y = *p
調用未定義的行為; x
引用的對象是自動的,當x
超出范圍時,它的生命周期結束。
變量的作用域和生命周期之間有什么關系?
正如奧利所說,變量有作用域和對象生命周期。 變量的范圍和它的生命周期是綁定的,但是你可以擁有生命周期超出創建它們的范圍的對象:
int* f() {
int *p // Variable p
= new int(1); // object (call it x)
return p; // p scope ends, p lifetime ends, x survives
}
int main() {
int *q // Variable q
= f(); // ... points to x
delete q; // x lifetime ends, q is in scope, q is alive
}
在您的特定情況下, x
變量在創建它的范圍關閉時結束其生命周期,因此您具有未定義的行為。
如果一個變量超出范圍,它的內存是否允許被另一個變量覆蓋,或者是否保留空間直到函數離開。
這是一個實現細節。 訪問變量在所有情況下都是未定義的行為,因為並非所有情況都必須相等,並且如果變量具有非平凡的析構函數,它將在作用域的末尾被調用,因此內存是否存在無關緊要:該對象不再存在。 也就是說,在許多情況下,當變量超出范圍時,編譯器不會釋放函數中的內存(即它們不會重新設置幀指針),但它們可能會重用相同的空間來保存同一函數中的其他變量。
我已經運行了你的程序,輸出是 5。盡管 x 變量在第二個 '}' 之后被銷毀,但輸出仍然是 5 是因為內存位置沒有被任何其他變量覆蓋。如果之后你有很多代碼第二個作用域的結尾,很可能之前由 'x' 擁有的內存位置被覆蓋了。
int x = 5;
*p = &x;
} // x lifetime ends after this.but the number '5' is still there in that memory.
//but it is possible to assign this memory (which previously belong to x) to a new var.
標准定義了一旦離開范圍就允許覆蓋內存。 編譯器實現使其保留和釋放。 編譯時優化可能會移動堆棧的分配,因此它們將不再反映您的順序。
您的代碼確實調用了未定義的行為,不應使用。 您的代碼實際上可能有效,因為在取 p 指向的值之后寫入 y 的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.