如何将streamsize转换为其他值或如何将streamsize值传递给vector?

时间:2018-11-24 14:52:53

标签: c++ windows visual-studio

我有一个问题,我需要将streamsize值传递给vector。如果我不通过它到固定大小。它将与带有1000个元素的emplace_back产生开销。错误编译器可能会导致数据丢失。

ifstream input(i_inputFilePath, ios::binary);
if (input.is_open())
{
    ofstream output(o_outputFilePath, ios::binary);
    std::array<char, 1024> buffer;
    while (true) {
        input.read(buffer.data(), buffer.size());
        streamsize dataSize = input.gcount();
        if (dataSize) 
        {
            std::vector<char> data(dataSize); // here the problem
            for (DWORD i = 0; i < dataSize; i++)
            {
                data.emplace_back(buffer[i]);
            }
            std::rotate(data.begin(), data.begin() + 1, data.end());
            output.write(data.data(), dataSize);    
        }
        else 
        { 
            output.close();
            input.close();
            break;
        }   
    }
}
else
{
    cout << "File is not exist";
}

1 个答案:

答案 0 :(得分:2)

如果将单个整数参数传递给std::vector的构造函数(如std::vector<char> data(dataSize);),则它将默认构造为其中的许多元素,其大小将为传递的整数。

如果您随后emplace_back进入它,它将增加其大小,而不会覆盖已经构造的元素。

如果您想emplace_back的所有元素,只需这样做,而无需将最终大小传递给构造函数:

std::vector<char> data;

std::vector的大多数实现都不会在每个emplace_back上重新分配,但是例如每次空间用完时将分配的空间加倍。因此,平均而言,这并没有那么糟糕。

如果您担心重新分配,则可以强制向量使用以下方式预分配空间

data.reserve(dataSize);

这实际上不会构造任何元素,但要确保事先分配了必要的空间。

如果您收到有关从std::streamsizestd::size_t的转换的错误消息,则此消息为假阳性,因为在这种情况下,您知道dataSize只能具有值范围从01024。编译器在警告dataSize的类型为带符号的警告时是正确的,因此可能持有std::size_t不能表示的负值,该值是无符号的。

您可以使用类似的方法测试该假设是否正确

streamsize dataSize = input.gcount();
if(dataSize < 0 || dataSize > buffer.size()) {
    throw std::range_error("dataSize has unexpected value!");
}
data.reserve(static_cast<std::size_t>(dataSize));    

这可以确保dataSize不会意外地为负值或大于预期值(如果为负值,则不会抛出异常),否则将提示编译器您确实想使用显式强制转换,应禁止显示警告/错误消息。