c++回调函数接收数组必须声明为int* data, size_t size,因数组形参必退化为指针,无法通过sizeof获取长度,需调用方显式传入大小。

回调函数参数怎么声明才能接收数组指针和长度
直接传 int* 和 size_t 是最常用也最安全的方式。C++ 没有“数组类型参数”,形参写 int arr[] 或 int arr[10] 都会退化为 int*,本质还是指针 + 长度分离传递。
关键在于:调用方必须主动把大小作为独立参数传入,回调函数内部不能靠 sizeof 算长度——因为传进来的是指针,sizeof(arr) 永远是 8(64 位系统)。
示例声明:
using Callback = void(*)(int* data, size_t size);
void process_data(int* arr, size_t n, Callback cb) {
if (cb) cb(arr, n);
}
std::vector 能不能直接传进回调函数
可以,但要注意所有权和生命周期。如果回调函数只是读取数据,传 const std::vector<int>&</int> 最方便;但如果回调要修改或长期持有数据,就得传指针+大小,或者用 std::shared_ptr<:vector>></:vector>。
常见错误是临时构造 vector 后传引用:
// ❌ 危险:临时对象在 process_data 返回后就销毁
process_data(some_ints, [](const std::vector<int>& v) { use(v); });</int>
正确做法:
- 提前构造好
std::vector并确保其生命周期覆盖回调执行期 - 或改用原始指针+大小接口,由调用方管理内存
- 避免在回调里保存对临时
vector的引用
使用函数对象(lambda / std::function)时怎么捕获数组
lambda 捕获数组本身没意义(栈数组不能跨作用域),真正要捕获的是指向它的指针和长度,或者整个 vector 对象。
注意点:
- 用
[&]捕获局部std::vector是安全的,前提是回调同步执行且 vector 不提前析构 - 用
[=]捕获 vector 会触发拷贝,大数组时有性能开销 - 捕获原始指针(如
int* p = arr;)必须确保所指内存有效,尤其异步回调中极易悬空
典型安全写法:
std::vector<int> data = {1,2,3,4,5};
process_data(data.data(), data.size(), [&data](int*, size_t) {
// 可安全访问 data,因为 data 在 lambda 外部仍存活
});</int>
回调里访问数组越界怎么快速定位
越界通常不报错,而是读到脏数据或崩溃,调试困难。建议在回调入口加轻量断言:
[](int* arr, size_t size) {
assert(arr != nullptr);
assert(size > 0);
// 避免用 arr[size] 或 arr[-1] 这类隐式越界
for (size_t i = 0; i <p>更彻底的方法:用 <code>std::span<int></int></code>(C++20)替代裸指针+大小,它自带边界检查(debug 模式下)且语义清晰:</p><pre class="brush:php;toolbar:false;">using Callback = void(*)(std::span<const int>);
// 调用侧:cb(std::span{vec});</const>不过要注意 std::span 不拥有数据,仍需保证底层内存不提前释放。
裸指针配大小看着土,但在跨语言、嵌入式或兼容 C ABI 场景下仍是事实标准;而 std::span 和 std::vector 引用更适合纯 C++ 内部逻辑——选哪个,取决于你控制不了的那一端是什么。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











