2014-11-08 220 views
3

在C++中執行goto語句時,以下代碼片段中的兩個數組是否從堆棧中移除?或者當方法返回時它們會從堆棧中移除?C++中的goto語句在堆棧中的效果

retrySplit: 
    ... 
    uint32_t primsAbove[primitives.size()]; 
    uint32_t primsBelow[primitives.size()]; 
    ... 
    goto retrySplit; 

這個問題是不相關的使用goto語句導致泄漏,但關心你是否能炸掉你的籌碼的可能性。

+2

從概念上講,它們在退出塊時被移除(即在關閉支撐處}} ... – 2014-11-08 14:29:58

+0

@BasileStarynkevitch,所以如果它是方法主流的一部分,它們將在返回後從堆棧中移除。 – Matthias 2014-11-08 14:33:13

+0

你不應該關心堆棧指針。這些局部變量的位置可能會在退出塊後重新使用。 – 2014-11-08 14:34:49

回答

4

此程序:

#include <iostream> 

class X { 
public: 
X() { std::cout << "ctor" << std::endl; } 
~X() { std::cout << "dtor" << std::endl; } 
}; 

int main(int argc, char** argv) { 
int i = 0; 

label: 
X a; 

if (i == 0) { 
    i = 1; 
    goto label; 
} 

return 0; 
} 

產生這樣的輸出:

$ ./a.out 
ctor 
dtor 
ctor 
dtor 
3

是的,數組被破壞。 [stmt.jump]/2:

在從範圍(但是完成),與已經構建在該範圍內是 在相反的順序進行破壞自動 存儲持續時間(3.7.3)對象出口他們的建設。 [...] 轉移出 循環的,出的塊,或回過去與 自動存儲持續時間的初始化變量包括在範圍上的點處與 自動存儲持續時間的對象的破壞從轉移 但不在轉移到的地步。

您也可以通過下面的代碼片段驗證這一點:

#include <iostream> 

struct A 
{ 
    A() {std::cout << "A";} 
    ~A() {std::cout << "D";} 
}; 

int main() 
{ 
    int counter = 0; 

    label: 
     if (counter++) // Exit on second run. 
      return 0; 

     A a; 
     goto label; 
} 

Demo。你的輸出應該是AD。 還要注意,counter在跳回label時不會被破壞。

+0

我知道A會被摧毀,但是我的問題是A會在打完電話後或者打完電話後被銷燬。 – Matthias 2014-11-08 14:41:13

+0

@Matthias什麼回電後?您應該提供了一個完整但簡約的示例,並顯示您不知道對象是被破壞的哪些行。 – Columbo 2014-11-08 14:51:17

+0

我的錯,但@ vz0覆蓋它。我擔心的是第二個'dtor'的位置 - > ctor,dtor,ctor,dtor,dtor – Matthias 2014-11-08 14:54:25

1

當它們超出範圍時(點擊右括號),它將從堆棧中移除,因此它確實取決於您的goto將要進入的位置。

另外這是一個側面說明,但爲什麼你使用goto?你應該看看它們,因爲它們有點臭名昭着。

+0

我正在修改現有的代碼。這是迄今爲止我見過的唯一一個'goto',它在一個非常性能的關鍵部分。 – Matthias 2014-11-08 14:35:07

+0

性能至關重要嗎?你沒有兌現規模價值,所以你必須檢索兩次。如果你還沒有完成基礎知識,我相信還有其他的優化。我不瞭解你的技能水平,但如果你是初學者,請注意其他編碼者會嚴厲地評判你的這種行爲。 – marsh 2014-11-08 15:45:17

+0

這只是一個快速繪製,我也可以使用單個數組。讓它工作 - >讓它正確 - >讓它快速。 goto已經是別人循環的結果。其次,編譯器不會在Ox或O3中獲取兩次大小(取決於您喜歡哪一個)的模式。 – Matthias 2014-11-08 17:34:29

1

爲了從堆棧中除去與地活着是兩個不同的事情。在你的例子中,數組棧中的內存可以被保留,但是在跳轉到標籤之後,數組將被視爲不活動。那就是在數組元素的跳轉析構函數被調用之前,以及當數組元素的構造函數被調用時控件實現數組的定義之前。