我有一个问题,我需要将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";
}
答案 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::streamsize
到std::size_t
的转换的错误消息,则此消息为假阳性,因为在这种情况下,您知道dataSize
只能具有值范围从0
到1024
。编译器在警告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
不会意外地为负值或大于预期值(如果为负值,则不会抛出异常),否则将提示编译器您确实想使用显式强制转换,应禁止显示警告/错误消息。