<p>不能直接用 std::vector 接收 int* 参数,因其不携带长度与所有权信息,强行构造易致 double-free 或悬空指针;需依场景选用 .data() 传参、预留空间或移动构造并手动释放。</p>

为什么不能直接用 std::vector 接收 int* 参数
因为 C 风格 API(比如 void process_data(int* data, size_t len))只传裸指针和长度,不携带所有权或边界信息。你不能把 int* 直接“赋值给” std::vector,它不会自动推导长度,也不会接管内存——强行构造可能引发 double-free 或悬空指针。
三种安全转换方式及适用场景
核心原则:明确谁负责释放内存、是否需要拷贝、是否允许修改原数据。
- 若 API 只读且你已有
std::vector,用.data()和.size()传参:process_data(vec.data(), vec.size()); - 若 API 输出结果到数组(如
fill_buffer(char* out, size_t cap)),先预留空间再传.data():std::vector<char> buf(1024); fill_buffer(buf.data(), buf.size());</char>(注意:不能用resize(0)后再传,.data()可能失效) - 若 API 返回堆分配的
int*+ 长度(如int* get_items(size_t* out_len)),用std::vector移动构造(C++11 起):size_t len; int* raw = get_items(&len); std::vector<int> v(raw, raw + len); free(raw);</int>(别漏掉释放)
常见坑:std::span 不是万能解药
std::span(C++20)确实能包装裸指针+长度,但它仍是非拥有型视图。以下写法看似简洁,实则危险:
int* ptr = new int[100]; auto s = std::span(ptr, 100); // OK // ... 但 ptr 仍需手动 delete[],span 不管生命周期 delete[] ptr; // 必须做 // s 现在是悬空 span —— 编译器不报错,运行时 UB
除非你能 100% 确保原始内存生命周期长于 span 使用范围,否则别用 span 替代容器。
立即学习“C++免费学习笔记(深入)”;
跨语言/ABI 边界时的特别提醒
如果这个 C API 是动态库导出函数(如 Windows DLL 或 Linux .so),参数类型必须保持 ABI 兼容。此时绝不能把 std::vector 当参数传入——它的内存布局、构造函数、异常行为都不在 C ABI 范围内。所有交互点必须严格使用 T* + size_t 组合,容器仅用于 C++ 层内部处理。
真正容易被忽略的是:哪怕你用 std::vector 封装了调用逻辑,只要涉及 DLL 导出函数、回调函数参数、或结构体中嵌套数组字段,就永远得回到裸指针+长度这一层。现代容器是工具,不是胶水。


















