为何在类成员函数中用指针求数组长度得垃圾值,main函数却正常?
数组参数传递导致长度计算异常的原因与解决方法
问题根源
- 数组参数的退化特性:当数组作为函数参数传递时,不管形参写的是
int arr[]还是int* arr,编译器都会将其视为int*指针。也就是说,fun类的len函数里,arr已经不是数组类型,而是一个普通的指针变量。 - main函数中的合法计算:
main里的arr是真正的数组类型(int[7]),&arr是指向整个数组的指针(类型为int (*)[7])。&arr + 1会指向数组末尾之后的内存位置,用这个地址减去数组首地址arr,得到的就是数组的元素个数7,这是符合C++规则的合法计算。 - 成员函数中的垃圾值原因:
len函数里的arr是指针变量,&arr是指向这个指针的指针(类型为int**)。&arr + 1指向的是该指针变量在内存中后续的位置,此时*(&arr + 1)取到的是指针变量后面的随机内存值,用它减去arr(原数组的首地址),得到的自然是无意义的垃圾值。
解决方法
方法1:手动传递数组长度
最直接的方式,调用函数时同时传入数组长度:
class fun { public: int len(int arr[], int size) { return size; } }; int main() { int arr[7] = {1,2,3,5,7,5,6}; fun obj; int size = obj.len(arr, 7); // 手动传长度 cout << size; return 0; }
方法2:用模板函数推导数组长度
利用模板让编译器自动推导数组的实际大小,同时用数组引用避免参数退化:
class fun { public: template <size_t N> int len(int (&arr)[N]) { // 数组引用作为参数,保留数组类型信息 return N; // 直接用推导出来的N,或者用你原有的计算方式也可以:return *(&arr + 1) - arr; } }; int main() { int arr[7] = {1,2,3,5,7,5,6}; fun obj; int size = obj.len(arr); // 编译器自动推导数组大小 cout << size; return 0; }
方法3:使用标准库容器
推荐使用std::array或std::vector,它们自带size()方法,无需手动计算长度:
#include<iostream> #include<array> using namespace std; class fun { public: template <size_t N> int len(const array<int, N>& arr) { return arr.size(); } }; int main() { array<int,7> arr = {1,2,3,5,7,5,6}; cout << arr.size(); // 直接获取长度 fun obj; int size = obj.len(arr); cout << size; return 0; }
内容的提问来源于stack exchange,提问作者Tanishq Khandelwal
相关产品推荐
相关产品推荐

