在基于范围的for循环中设置矢量元素

时间:2015-02-24 13:39:16

标签: c++ c++11

在分配给动态分配的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,那么事情就像我期望的那样。

我错过了什么?

4 个答案:

答案 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#背景,循环遍历你的矢量就像是对我的憎恶,更不用说你设置每个元素两次。另外,如果在任何时候你的元素生成都失败了,那么你将会得到一堆原本不应该存在的零。