2015-02-24 78 views
2

當分配給動態分配的std::vector的元素時,我遇到了與C++ 11基於範圍的for循環相關的奇怪行爲。我有以下代碼:在基於範圍的循環中設置矢量元素

int arraySize = 1000; 
std::string fname = "aFileWithLoadsOfNumbers.bin"; 
CTdata = new std::vector<short int>(arraySize, 0); 
std::ifstream dataInput(fname.c_str(), std::ios::binary); 
if(dataInput.is_open() 
{ 
    std::cout << "File opened sucessfully" << std::endl; 
    for(auto n: *CTdata) 
    { 
     dataInput.read(reinterpret_cast<char*>(&n), sizeof(short int)); 
     // If I do "cout << n << endl;" here, I get sensible results 
    } 
    // However, if I do something like "cout << CTdata->at(500) << endl;" here, I get 0 
} 
else 
{ 
    std::cerr << "Failed to open file." << std::endl; 
} 

如果我改變循環到一個更傳統的for(int i=0; i<arraySize; i++)和到位的&n在讀功能使用&CTdata->at(i),做的事情,因爲我期望的那樣。

我錯過了什麼?

回答

5

改變這種循環語句

for(auto n: *CTdata) 

for(auto &n : *CTdata) 

那就是你必須使用引用向量的元素。

1

你必須寫

for(auto& n : *CTdata) 

因爲auto n意味着short int n當你需要short int& n。 我建議你閱讀decltype和auto之間的區別。

1

你的循環失敗的原因是因爲你通過值引用矢量元素。但是,在這種情況下,您可以完全消除循環:

dataInput.read(reinterpret_cast<char*>(CTdata->data()), arraySize*sizeof(short int)); 

這會在單次調用中將內容讀入向量中。

0

弗拉德的答案完美地回答你的問題。

但是,請考慮一下。您可以調用vector<>::reserve()來預先分配您的後備緩衝區而不更改向量的前向部分,而不是從頭開始填充零。

然後,您可以像平常一樣調用vector<>::push_back(),而不會影響性能,同時仍然保持源代碼中的邏輯清晰。從C#背景來看,循環遍歷你的向量看起來像對我的憎惡,更不用說你設置每個元素兩次。另外,如果在任何時候你的元素生成失敗了,你會得到一堆不應該在那裏出現的零。