用C++中的迭代器将向量写入二进制文件的正确方法

问题描述

搜索了很多此类问题,但没有得到满意的答案。

我正在开发一个函数,使用 C++ 中的 ofstream::write 方法将向量容器写入二进制文件

#include <vector>
#include <fstream>

typedef std::vector<unsigned char> byteArray;

byteArray data;
data.push_back('a');
data.push_back('b');
data.push_back('c');
data.push_back('d');

std::ofstream fout("out_file",std::ios::out | std::ios::trunc | std::ios::binary);

// I kNow the right way should be as following:
fout.write((char *)&data[0],data.size());

// But what I cannot understand is why the following expression is wrong,since gcc compiler says
// invalid cast from type ‘__gnu_cxx::__normal_iterator<unsigned char*,std::vector<unsigned char> >’ to type ‘char*’

for(auto iter = data.begin(); iter != data.end(); iter++)
{
    fout.write((char *)iter,1);
}

fout.close();

据我所知,迭代器 iter 是一个指针,指向向量“数据”中的一个元素。所以我认为(char *) iter会将底层数据类型重新解释为char,那么它应该满足fout.write的参数要求。但实际上,情况并非如此。我也很困惑 gcc 说 iter 是一种 iterator ,对吧? iter 不应该是 unsigned char * 类型吗?

我做错了什么?非常感谢您的帮助。

解决方法

据我所知,迭代器 iter 是一个指针

事实并非如此。 std::vector::iterator 是未指定的类型。

您可以期望它具有一些类似指针的属性,但您不应假设它可能是什么特定类型。

因为你需要一个指针,解引用迭代器并获取结果的地址。那是一个指针。

fout.write((char *)&*iter,1);

更好的是,使用 C++ 强制转换而不是难以跟踪的 C 强制转换。

fout.write( static_cast<char*>(&*iter),1 );

甚至更安全(Martin York 始终是一颗珍贵的宝石)——不要假设所包含类型的大小。未来可能会改变。这一变化不会增加任何过度。

fout.write( static_cast<char*>(&*iter),size_of(byteArray[0]) );
,

指针可以用作迭代器,但迭代器不一定是指针。

迭代器通过提供取消引用 operator*()、递增 operator++() 等的操作,或多或少地像一个指针,请参阅例如的要求。 LegacyInputIterator

尽管具体定义会随着时间而改变,但请参阅 std::input_or_output_iterator 以了解 C++20 中的定义。