因为数组传参会退化为指针,sizeof(arr)返回指针大小而非数组总字节数;推荐用模板函数array_size通过引用绑定保留维度信息,编译期推导长度。
![c++数组作为形参后sizeof(arr)/sizeof(arr[0])算错怎么解决](https://img.php.cn/upload/article/001/221/864/179031187844624.png)
为什么 sizeof(arr)/sizeof(arr[0]) 在函数内失效
因为 C++ 数组作为形参传入函数时,会自动退化为指针,arr 不再是数组类型,而是 T*。此时 sizeof(arr) 返回的是指针大小(通常是 4 或 8 字节),不是原始数组总字节数,除法结果必然错误。
用模板推导数组长度(推荐)
让编译器在编译期捕获数组大小,避免运行时退化。关键在于用引用绑定数组,保留维度信息:
template <typename T, size_t N>
size_t array_size(const T (&)[N]) {
return N;
}调用时直接传数组名即可:
int a[] = {1, 2, 3, 4};
std::cout << array_size(a); // 输出 4- 只适用于真实数组(栈上定义、非 new 分配)
- 不能用于函数参数中已退化的
int*变量 - 若需支持 const 修饰,模板参数加
const T(&&)[N]即可
改用 std::array 或 std::vector
现代 C++ 更应避免裸数组。两者都自带 .size() 方法,语义清晰且无退化问题:
立即学习“C++免费学习笔记(深入)”;
void f(const std::array<int, 5>& arr) {
std::cout << arr.size(); // 安全,始终为 5
}
void g(const std::vector<int>& vec) {
std::cout << vec.size(); // 运行时确定,但不会算错
}-
std::array适合编译期尺寸固定、无需动态扩容的场景 -
std::vector适合大小不确定或需增删元素的情况 - 二者传参建议用 const 引用,避免拷贝开销
如果必须用裸数组指针,就别依赖 sizeof
一旦形参声明为 int arr[] 或 int* arr,编译器就丢掉了长度信息。这时唯一可靠做法是额外传入长度参数:
void process(int* arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
// 使用 arr[i]
}
}- 这是 C 风格兼容写法,明确、可控
- 切勿在函数内对
arr做sizeof运算——它永远不是你想要的 - 若调用方本身也是从另一个函数接收的指针,那长度必须由上游明确传递,无法自动恢复
C++ 数组退化是底层机制决定的,不是 bug,但容易误用。真正麻烦的不是“怎么修”,而是“什么时候意识到它已经退化了”——尤其当函数签名看着像接受数组,实际却只收了指针。


















