首页 > 解决方案 > 为什么 std::ostreambuf_iterator 截断整数?

问题描述

我将 uint32_t 数字的排序向量通过 复制到二进制流中std::copy(numbers.begin(), numbers.end(), std::ostreambuf_iterator<char>{stream}),但它会截断数字,将它们转换为 1 字节数字。

我的代码有什么问题?我有一个解决方法,但也许可以使 ostreambuf_iterator 方法正常工作?

std::ofstream chunk{ "filename.txt", std::ios::binary | std::ios::out };

// this piece of code works not expected
std::copy(numbers.begin(), numbers.end(), std::ostreambuf_iterator<char>{chunk});

// But this, alternative works good
for (auto& v : numbers)
    chunk.write((char*)& v, sizeof uint32_t);

我希望有这个输出:

0000 0000 0000 0000 0000 0000 0100 0000
0100 0000 0100 0000 0100 0000 0100 0000

但我的输出是:

0000 0000 0000 0000 0000 0000 0101 0101
0101 0101 0101 0101 0101 0101 0101 0101

标签: c++stl

解决方案


我将 uint32_t 数字的排序向量通过 复制到二进制流中std::copy(numbers.begin(), numbers.end(), std::ostreambuf_iterator<char>{stream}),但它会截断数字,将它们转换为 1 字节数字。

是的 - 你要求它!

你有一个范围uint32_t,那么你正在使用一个char迭代器。

因此,每个元素在经过时都会转换为 a char

std::ostreambuf_iterator<char>不会自动为不同类型的输入元素起别名。这在大多数情况下是非法的,而且它必须进行缓冲以(在此示例中)为每个输入提供四个输出:现在假设您将chars 提供给 a ostreambuf_iterator<uint32_t>,并意识到它必须为每四个提供一个输出输入,这变得更加复杂。这不是这个迭代器的用途。

您将希望将该范围视为一个范围char;幸运的是,由于别名豁免,这是合法的。我们不能再使用向量迭代器了,但这很好,因为我们可以以指针的形式直接访问它的连续数据,并用这些指针做我们喜欢的事情:

std::copy(
   reinterpret_cast<const char*>(numbers.data()),
   reinterpret_cast<const char*>(numbers.data() + numbers.size()),
   std::ostreambuf_iterator<char>{stream}
);

这实际上等同于您的第二个示例。


推荐阅读