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

Setting vector elements in range-based for loop

本文关键字:循环 设置 元素 for 于范围 范围      更新时间:2023-10-16

在分配给动态分配的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,事情就会如我预期的那样进行。

我错过了什么?

更改此循环语句

for(auto n: *CTdata)

for(auto &n : *CTdata)

也就是说,您必须使用对向量元素的引用。

你必须写

for( auto& n : *CTdata )

因为auto n意味着short int n当你需要short int& n.我建议您阅读差异Beetween Decltype和Auto。

循环失败的原因是按值引用向量元素。但是,在这种情况下,您可以完全消除循环:

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

这会在一次调用中将内容读入向量。

弗拉德的回答完美地回答了你的问题。

但是,请考虑一下。与其从一开始就用零填充数组,不如调用 vector<>::reserve() ,它预先分配您的后备缓冲区,而无需更改矢量的前向部分

然后,您可以像往常一样调用vector<>::push_back(),而不会对性能造成任何影响,同时仍保持源代码中的逻辑清晰。来自 C# 背景,像这样循环使用矢量对我来说似乎是可憎的,更不用说你为每个元素设置了两次。另外,如果你的元素生成在任何时候失败,你会有一堆本来就不应该存在的零。