将向量的内容写入文件作为二进制数据

时间:2017-11-08 22:53:40

标签: c++ vector

我有一些已有15年历史的C ++代码,我试图将其带到更现代的时代。在这个阶段,我试图获得使用Visual C ++ 6.0编译的代码,现在使用VS 2003进行编译(Microsoft Visual C ++ .NET 69462-335-0000007-18915)。

std::vector<myClassType> myVect;
...

// Assuming vector.begin() simply points to start of a contiguous array
bool OK = File.write((char*) myVect.begin(),
                     myVect.size() * sizeof(myClassType));

当我阅读评论时,我会担心...我们真的可以假设一个向量在连续的内存中吗?如果没有,有什么更好的方法呢?我是否需要遍历矢量内容&amp;从myClassType写出每组数据?

实际上,编译器抱怨将begin()的结果转换为char *。

2 个答案:

答案 0 :(得分:4)

std::vector保证将其元素存储在连续的内存中,因此,如果myClassTypePOD type,您尝试执行的操作就可以了。否则,您必须循环遍历std::vector,根据需要将每个元素一次一个地序列化为平面格式。

但是,std::vector::begin()方法将迭代器返回给元素数据的第一个元素,而不是指针。迭代器是指针,但是不是指针。容器实现被允许使用实际指针作为迭代器,但更多次使用包装类。不要依赖这种行为!按照预期的方式使用迭代器API,并且不要假设迭代器是实际的指针。

要获得指向矢量第一个元素数据的有效指针,您需要:

  1. 使用std::vector::data()(仅限C ++ 11及更高版本):

    myVect.data()
    

    即使向量为空,这也是安全的。当data()为0时,nullptr可能会或可能不会返回size(),但这是正常的,因为write()size()为0时不会尝试访问任何内存。

    bool OK = File.write((char*) myVect.data(), myVect.size() * sizeof(myClassType));
    
  2. 使用std::vector::operator[]获取对第一个元素的引用,然后使用operator&获取元素的地址:

    &myVect[0]
    

    请注意operator[]不执行边界检查,因此如果指定的索引是&gt; = size(),将返回未定义的指针,因此在写入之前一定要检查向量是否为空:

    bool OK = myVect.empty() || File.write((char*) &myVect[0], myVect.size() * sizeof(myClassType));
    
  3. 与#2相同,但改为使用std::vector::front()

    &myVect.front()
    

    请注意,在空向量上调用front()是未定义的行为,因此请务必检查向量是否为空:

    bool OK = myVect.empty() || File.write((char*) &myVect.front(), myVect.size() * sizeof(myClassType));
    
  4. 使用begin()获取第一个元素的迭代器,然后使用operator*取消引用迭代器以获取对其指向的元素的引用,然后可以获取元素的地址:

    &(*(myVect.begin()))
    

    注意begin()在向量为空时返回end()迭代器,并且取消引用end()迭代器是未定义的行为,因此请务必检查向量是否为空:

    bool OK = myVect.empty() || File.write((char*) &(*(myVect.begin())), myVect.size() * sizeof(myClassType));
    

答案 1 :(得分:4)

Remy Lebeau的回答是正确的。要添加它,如果您想为代码添加更多安全性,还应使用static_assert确保myClassType可以安全地编写,如下所示:

#include <type_traits>
static_assert(std::is_pod_v<myClassType>, "myClassType is potentialy unsafe to write as-is");

如果有人在将来以myClassType代码中使用不安全的方式修改File.write(),则此编译时检查将捕获它。

相关问题