2010-05-29 67 views
0

我發現VS2005 C++編譯器這個奇怪的行爲。這裏是的情況:在構造函數的const參數導致stackoverflow

我不能發佈代碼,但情況很簡單。

這裏是最初的代碼:它的工作完美

class Foo { 
    public: 
    Foo(Bar &bar) { ... } 
} 

的構造函數實現存儲參考,設置一些成員的確...沒有什麼特別的。

如果我更改以下列方式代碼:

class Foo { 
    public: 
    Foo(const Bar &bar) { ... } 
} 

我添加了一個const限定的唯一構造常規參數。

它編譯正確,但編譯器輸出一個警告,說例程Foo :: Foo將導致一個stackoverflow(即使執行路徑不構造任何對象Foo);有效地發生。

那麼,爲什麼不常量參數代碼工作完美,而一個與常量限定詞使一個計算器?什麼會導致這種奇怪的行爲?

+2

您需要發佈兩個代碼和編譯器警告你得到。 – 2010-05-29 08:53:14

+4

無法告知這些信息。我們需要更多的信息或可以複製警告的最小代碼 – Naveen 2010-05-29 08:54:17

+0

真的嗎?我使用C++編譯器版本爲15.00.30729.01的VS2005,並且這兩個代碼片段(使用'class Bar {};')都不會給我任何堆棧溢出警告,即使在最高警告級別。我錯過了什麼嗎? – 2010-05-29 08:56:57

回答

2

對這個問題的唯一解決辦法會導致堆棧溢出(除了在編譯器中的錯誤,這在我15年做C++的,我發現罕見相比,我自己的錯誤)是Foo(const Bar&)創建Foo對象傳遞一個Bar對象。通過查看代碼,像這樣的錯誤可能很微妙,很難找到。

但是如果你有VS2005,你手邊有一個相當不錯的調試器。在該構造函數中放置一個斷點,運行該程序,直至遇到斷點,然後再次運行,直至第二次觸發斷點。檢查堆棧會告訴你它是如何發生的。

如果不是每次調用此構造會導致堆棧溢出,您可以添加以下代碼:

namespace { unsigned int recursion_detector = 0; } 

Foo::foo(const Bar& bar) 
{ 
    if(recursion_detector++) 
    ++recursion_detector; // meaningless code just to put a breakpoint here 
    // rest of constructor code 
} 

將斷點就行表示,當發生遞歸將受到打擊。

4

請嘗試使用explicit關鍵字?

我的猜測是,與const,你聲明自動轉換從酒吧到美孚;如果你已經有類似的從Foo到Bar的自動轉換,那麼溢出?

0

您可以將參數從const Bar & bar更改爲const Bar * bar。 它會正常工作,你只需要改變你管理參數欄的方式(從引用到指針)。

對象初始化會是這樣的:

Bar mybar; 

... 

Foo myfoo(&mybar); 


class Foo { 
    public: 
    Foo(const Bar *bar) { ... } 
}; 

這並不是說不好......