在分配给动态分配的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++)
并在读取函数中使用&CTdata->at(i)
代替&n
,那么事情就像我期望的那样。
我错过了什么?
答案 0 :(得分:6)
更改此循环语句
for(auto n: *CTdata)
到
for(auto &n : *CTdata)
你必须使用对向量元素的引用。
答案 1 :(得分:1)
你必须写
for( auto& n : *CTdata )
因为当您需要auto n
时,short int n
表示short int& n
。
我建议你阅读decltype和auto之间的差异。
答案 2 :(得分:1)
循环失败的原因是因为您按值引用向量元素。但是,在这种情况下,您可以完全消除循环:
dataInput.read(reinterpret_cast<char*>(CTdata->data()), arraySize*sizeof(short int));
这会在一次调用中将内容读入矢量。
答案 3 :(得分:0)
弗拉德的回答完美地回答了你的问题。
然而,请考虑一下。您可以调用vector<>::reserve()
来预先分配您的后备缓冲区而不更改向量的正面部分,而不是从头开始填充零。
然后,您可以像平常一样调用vector<>::push_back()
,而不会影响性能,同时仍然保持源代码中的逻辑清晰。来自C#背景,循环遍历你的矢量就像是对我的憎恶,更不用说你设置每个元素两次。另外,如果在任何时候你的元素生成都失败了,那么你将会得到一堆原本不应该存在的零。