2012-08-04 98 views
4

我有一個C++的基本程序,它列出了給定數量的素數。做這個工作的類是下面的 - 我的問題是,當「金額」的輸入是10(特別是10 - 對我嘗試過的所有其他數字都能正常工作)時,下面生成的數組不會被初始化爲一個零數組。因此,「數組的最後一個元素爲空」返回false,並且我的代碼無法正常運行。爲什麼int數組在C++中未初始化爲零?

我不知道我是否誤解了,但不應該int數組初始化爲零?如果不是,整數10的特殊性導致它初始化爲奇怪的值?

int* primecalc(int amount) { 

int* primes = new (nothrow) int [amount]; 

//Throw an error if we can't allocated enough memory for the array. 
if (primes==0) { 
cout<< "Error allocating memory."; 
return 0; 
} 

//Otherwise, start iterating through the numbers. 
else { 
primes[0] = 2; 
primes[1] = 3; 

int p = 2; 

for (int i=4;primes[amount]==0;i++) { 
int j = 0; 
int k = 0; 

    while ((primes[j]<=floor(i/2)) && !(primes[j]==0) && (k==0)) { 

     if ((i % primes[j]) == 0) { 
     k=1; 
     } 
    j++; 
    } //end the while loop 

if (k==0) { 
     primes[p] = i; 
     p++; 

} 

} //end the for loop 

} //end the "else" part (this was only necessary in case memory could not be allocated) 

return primes; 
} 

我也嘗試沒有(nothrow),具有相同的結果。預先感謝任何幫助!

+6

爲什麼你期待新的數組初始化? – YePhIcK 2012-08-04 23:17:53

+3

請注意'primes [amount] == 0'調用未定義的行爲。到primes的有效索引是0到'amount-1'。 – 2012-08-04 23:21:12

+0

@DanielFischer啊,是的,我也應該解決這個問題。謝謝! – user1576713 2012-08-05 09:29:48

回答

13

int* primes = new (nothrow) int[amount];使用缺省初始化,其對於像int這樣的標量是一個noop(即沒有實際的初始化被執行)。

如果你想明確的初始化,使用值初始化代替:

int* primes = new (nothrow) int[amount](); 

從C++ 11標準,第8.5節/ 6:

默認 - 初始化T類型的對象表示:

  • 如果T是一個(可能是cv-qualified)類類型,則調用T的默認構造函數(如果T沒有可訪問的默認構造函數,則初始化不合格);
  • if T是一個數組類型,每個元素默認初始化;
  • 否則,不執行初始化

如果程序要求一個常量限定類型T的對象的默認的初始化,T應是一個類的類型與用戶提供的默認的構造。

§8。5/7:

值初始化T類型的對象是指:

  • 如果T是用用戶提供的構造(可能CV修飾)類型,則調用T的默認構造函數(如果T沒有可訪問的默認構造函數,則初始化不合格);
  • 如果T是一個(可能是cv合格的)非聯合類類型,沒有用戶提供的構造函數,那麼該對象是零初始化的,並且如果隱式聲明的默認構造函數是非平凡的,那麼構造函數叫做。
  • 如果T是一個數組類型,那麼每個元素都是值初始化的;
  • 否則,該對象是零初始化的

一個被初始化值的對象被認爲是構造的,因此受到本國際標準規定適用於「構造」對象,構造函數完成的對象「等,即使沒有爲對象的初始化調用構造函數。

第8.5節/ 6:

零初始化對象或T類型的引用意味着:

  • 如果T是標量類型,對象被設置取值爲0(零),作爲積分常數表達式,轉換爲T;
  • 如果T是一個(可能是cv-qualified)非聯合類類型,則每個非靜態數據成員和每個基類子對象都被初始化爲零,並且填充被初始化爲零位;
  • 如果T是一個(可能是cv-qualified)聯合類型,則該對象的第一個非靜態命名數據成員是零初始化的,並且將填充初始化爲零位;
  • if T是一個數組類型,每個元素都是零初始化的;
  • 如果T是引用類型,則不執行初始化。

最後,來自第8.5節/ 10:

一個對象,其初始化爲空集括號的,即,(),應值初始化。

(所有重點煤礦。)

+0

輝煌 - 謝謝! – user1576713 2012-08-05 09:28:39

3

這樣做只是爲了提高效率。並非所有情況下數組都必須預填充一個值,因此C++默認不會這樣做。

如果使用std::vector<int>而不是純陣列(我建議你),您有一個構造函數來設置初始值,該值可以是0:

std::vector<int> v(10,0); // 10 elements with 0 
+0

爲什麼downvote?儘管如果他們想要初始化,我們必須使用'std :: vector <>'的含義是_misleading_,但在這個答案中沒有看到任何東西是_incorrect_。 – ildjarn 2012-08-04 23:28:12

+0

好吧,我也不明白downvote,但SF看起來並不是一門精確的科學。另外,我並不意味着使用向量進行初始化。我說*如果* OP決定這樣做。我推薦它不只是爲了初始化,而是爲了更好的編程模式,所以謙虛地說我沒有看到這種誤導。當然,添加一個默認值的向量構造函數比爲一個過長而複雜的'new'調用添加一對圓括號要清楚得多,但這可能只是我的理解。 – 2012-08-04 23:41:06