2013-08-03 249 views
21

我剛剛從電子書開始學習C++。
我的代碼沒有任何錯誤,但我確實有一個問題。
書中使用下面的代碼來總結兩個數字:爲什麼變量初始化爲0?

#include <iostream> 
int main() 
{ 
    std::cout << "Enter two numbers:" << std::endl; 
    int v1 = 0, v2 = 0; 
    std::cin >> v1 >> v2; 
    std::cout << "The sum of " << v1 << " and " << v2 
     << " is " << v1 + v2 << std::endl; 
    return 0; 
} 

所以int v1 = 0,v2 = 0;用於變量。 他們爲什麼初始化爲0?

+2

它們的初始值爲零。否則,他們會包含一些隨機數據。 –

+0

,因爲這是初始化變量的最佳做法! –

+2

爲什麼不是零?你有特定號碼的偏好嗎? – Thomas

回答

15
int v1 = 0; 

這就是所謂的初始化,這是一個好習慣中。如果您不使用內置類型的初始值設定項,則其值將被調用爲,並且不確定,讀取此類值是非法的。如果你輸入一個字母而不是數字在第二行

int v1; 
std::cin >> v1; 
std::cout << v1; 

輸入操作可能會失敗,例如,和v1將保持不變:

讓我們假設你做到這一點。沒有檢查輸入是否成功,如果v1仍然發生未初始化,砰!你已經調用了未定義的行爲,你只需要編譯器的支持就可以做任何它想做的事情。

在您發佈的代碼,v1v2被初始化,即使輸入失敗,你至少獲得一些結果具有明確的行爲。

這就是說,不檢查輸入是否成功是一個邏輯錯誤。畢竟,0是一個有效的輸入可能性,沒有額外的檢查,沒有辦法確定這是用戶輸入的內容。

做到這一點的最簡單的方法是使用輸入表達式在布爾上下文,裏面if條件:

if (std::cin >> v1 >> v2) { 
    // good, use v1 and v2 
} else { 
    // bad input, we can't 
    // rely on v1 and v2 to 
    // have meaninful value here 
} 

流是隱式轉換爲bool,如果沒有錯誤標誌置位,計算結果爲true和否則爲false

完成上述檢查後,幾乎沒有需要初始化,因爲如果輸入失敗,我們將永遠不會觸及v1v2

+5

你的例子與初始化無關。如果讀取操作失敗,無論是否初始化,「v1」的值都是不確定的。 – rubenvb

+0

@rubenbv Huh?我在談論未初始化的變量。如果在嘗試通過'operator >>寫入變量之前初始化一個變量,即使'operator >>'失敗,它也會被初始化。如果發生這種情況,它的值可能不會被標準所指定(或是否檢查'27.7.2.2.2'),但是沒有UB。 – jrok

+0

我會感謝downvoters的反饋(根據現在編輯的答案)。 – jrok

1

定義它們時,通常會爲變量設置一個值。 有時,當您嘗試使用未初始化爲值的變量進行操作時,您會遇到錯誤的錯誤。

但在你的例子中,它並不重要,因爲你用cin read設置了一個值。

+0

不,這很重要。 'std :: istream :: operator >>'可能會失敗。 – Shoe

+0

@傑弗裏不,它不是。從標準輸入讀取後檢查值並在失敗時再次查詢用戶,這很重要。 –

+0

@ManuelGörlich,你會很重要嗎?這是什麼意思? – Shoe

13

這是一種常見的做法,但在這個例子中,這是一個解決方案,因爲沒有足夠的思考錯誤處理。如果你不初始化它們,那麼你可以得到一個無效值的合理化只有在你不打算檢查輸入是否成功時纔有意義。代碼不檢查輸入是否成功,所以它是致命的缺陷。沒有其他不必要的初始化可以解決這個問題。

std::cin >> v1 >> v2; 
if (std::cin) 
    std::cout << "The sum of " << v1 << " and " << v2 
     << " is " << v1 + v2 << std::endl; 
else 
    std::cout << "Bogus input\n"; 
0

雖然其他答案是正確的,但我不認爲它們很可能是這些變量初始化爲零的真正原因。

相反,我強烈懷疑的理由是這樣的:如果他們不是,大多數編譯器會發出有關使用未初始化變量警告。我相信這裏的初始化主要或純粹是爲了壓制發出警告。

+3

至少有一個編譯器會在這裏產生警告 – Abyx

-1

這是常見做法的一部分。

這是更好的值初始化的變量給它完整的感覺。

+0

不,它不會更好。見[這裏](http://stackoverflow.com/questions/18030997/why-are-variables-initialized-to-0/18031043#comment26378958_18031043)。 – Shoe

+0

實際上是這樣。 –

22

這是cargo cult programming。這不是有害的,但它在這裏沒有任何實際的益處,可能只是因爲作者想要爲了教學目的而簡化一個概念,或者是因爲他誤解了某些東西。

這是爲什麼。

通常,所有的變量應直接初始化一次聲明。這確保變量永遠不會處於不確定狀態。這使控制流程更簡單,代碼更容易推理,從而防止錯誤。

但是,這隻有在我們可以用一個有意義的初始化變量的情況下才有意義 - 即用它以後代表的值。在你的代碼,這種情況並非如此 - 而是變量讓他們的價值後分配,通過輸入流(不幸的是C++不支持初始化從輸入讀取值的變量簡明,規範的方法)。

正如@jrok說,初始化針對無效輸入並且在該代碼後續錯誤表面上警衛。我說表面上是,因爲這不是真的:我們初始化變量的值是 - 0 - 是也是在程序的上下文中無效,所以我們並沒有真正獲得任何東西。

傑克Aidley提供了此代碼的真正原因是爲了防止編譯器警告。但是由於上述原因,編譯器不應該在這裏發出警告。事實上,GCC 不會發出警告,即使在編譯時啓用了許多警告。也許其他編譯器可以,但我會考慮這個警告噪聲。

+0

同意,類似'int foo << cin;'會非常酷,但可惜,在C++中不可能這樣做,所以你只需要延遲初始化作爲你的唯一選擇... – Thomas

+3

@Thomas實際上我正在考慮更多'auto i = read (cin);'作爲一個圖書館解決方案,這很容易實現。 'read'會返回一個類似於'boost :: optional'的值,或者該函數可能會在失敗時拋出異常(但第一個變體有很多優點)。事實上,每當我的代碼嚴重依賴IO時,我都會使用這些函數。 –

相關問題