You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将vector<int>保存到bin文件读取得到随机数据,如何解决?

问题成因
  1. 你对非POD类型的二进制序列化逻辑完全错误:std::vector 作为动态容器,其对象本身仅存储指向堆上实际数据的指针、元素数量、容量三个元数据,真实的元素内容并不在vector对象的内存区间内。你直接对vector对象取地址写入sizeof(data)长度的内容,仅保存了vector的元数据(包括指向堆内存的指针值),完全没有写入真实存储的int元素。
  2. 第一个版本的输出1完全是偶然的未定义行为:你读写操作中间原vint对象未被销毁,其指向的堆内存还未被回收/覆盖,你读出来的load_vint里的指针恰好和原vint指向同一块内存,所以碰巧拿到了正确值,但此时load_vint和原vint持有同一个堆指针,二者析构时会触发重复释放,只是第一个版本程序刚好在崩溃前执行完了所有输出。
  3. 第二个版本提前崩溃是因为未定义行为的后果暴露:封装到testing函数后,对象生命周期的变化让堆内存提前被覆盖/重复释放的问题直接触发程序崩溃,所以没执行到done的输出就终止了。
修复方案

正确的vector序列化逻辑需要先存储元素数量,再存储所有元素的实际内容;读取时先读取元素数量给vector分配对应空间,再读取元素填充到vector中。你可以通过模板特化实现vector类型的专属读写逻辑,修复后的代码如下:

#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

// 针对POD类型的通用保存函数
template <typename T>
void save(string p_file, const T& data) {
    ofstream output(p_file, ios::binary | ios::out);
    output.write((char*)&data, sizeof(data));
    output.close();
}

// 针对vector的特化保存函数
template <typename T>
void save(string p_file, const vector<T>& data) {
    ofstream output(p_file, ios::binary | ios::out);
    // 先写入元素数量
    size_t size = data.size();
    output.write((char*)&size, sizeof(size));
    // 再写入所有元素的实际内容
    output.write((char*)data.data(), size * sizeof(T));
    output.close();
}

// 针对POD类型的通用读取函数
template <typename T>
T read(string p_file) {
    ifstream input(p_file, ios::binary | ios::in);
    T data;
    input.read((char*)&data, sizeof(data));
    input.close();
    return data;
}

// 针对vector的特化读取函数
template <typename T>
vector<T> read(string p_file) {
    ifstream input(p_file, ios::binary | ios::in);
    // 先读取元素数量
    size_t size;
    input.read((char*)&size, sizeof(size));
    // 初始化vector分配对应空间
    vector<T> data(size);
    // 读取所有元素到vector的存储空间中
    input.read((char*)data.data(), size * sizeof(T));
    input.close();
    return data;
}

void testing() {
    vector<int> vint;
    vint.push_back(1);
    save< vector<int> >("test.bin", vint);
    vector<int> load_vint = read< vector<int> >("test.bin");
    cout << vint[0] << endl;
    cout << load_vint[0] << endl;
}

int main() {
    testing();
    cout << "done" << endl;
    return 0;
}

注意:上述代码仅适用于存储POD类型(基础类型、仅含POD成员的结构体)的vector,如果vector存储的是std::string、自定义类等非POD类型,需要单独实现对应类型的序列化逻辑。

内容的提问来源于stack exchange,提问作者celphato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 00:45:04