C++固定大小数组作函数参数调用begin报无匹配函数问题
根本原因
C++ 中数组作为函数形参时存在默认的数组退化规则:你写的void test(int arr0[2])从语法上看是接收长度为2的int数组,但编译器实际会将该形参处理为int* arr0——方括号里写的长度常量2会被直接忽略,不参与类型判定。std::begin 针对数组的重载要求传入的参数必须是真正的数组类型(形如T[N],带有编译期可识别的长度信息),而退化后的arr0是裸指针,没有任何长度信息,无法匹配begin的数组重载,因此会报No matching function for call to 'begin'错误。
你代码里的arr1、arr2能正常调用begin,是因为二者都是函数内部定义的真实数组,类型分别为int[3]、int[2],带有完整的编译期类型和长度信息,可以正常匹配begin的数组重载,和是否用常量指定长度没有关系。
零开销解决方法(无需使用vector)
所有方法都没有额外运行时开销,和原生数组效率完全一致:
- 方法1:传固定长度数组的引用
给形参加上引用修饰,就能彻底阻止数组退化,明确要求传入长度为2的int数组,编译期会自动校验传入参数的长度是否匹配,写错长度直接编译报错:#define arr_size 2 // 注意&必须加括号,否则会被解析成int* arr0的引用 void test(int (&arr0)[2]){ int arr1[]={1,2,3}; int arr2[arr_size]; begin(arr0); // 正常工作 begin(arr1); // 正常工作 begin(arr2); // 正常工作 } - 方法2:用模板泛化支持任意长度数组
如果需要接收不同长度的int数组,可以用模板自动推导数组长度,编译期会为不同长度的数组生成对应实例,同样零开销:#include <cstddef> // 用于size_t #define arr_size 2 template<std::size_t N> void test(int (&arr0)[N]){ int arr1[]={1,2,3}; int arr2[arr_size]; begin(arr0); // 正常工作,编译期N会自动推导为传入数组的实际长度 begin(arr1); // 正常工作 begin(arr2); // 正常工作 } - 方法3:手动构造迭代器(不推荐,无编译期校验)
如果你因为兼容历史代码必须用指针形参,那直接用指针本身作为起始迭代器,手动计算结束迭代器即可,但这种方式需要你自己保证传入的数组长度确实为2,没有编译期安全校验:#define arr_size 2 void test(int arr0[2]){ // 裸指针本身就是随机访问迭代器 auto begin_it = arr0; auto end_it = arr0 + 2; }
注意:
void test(int arr0[常量])是C++从C继承来的过时语法,没有任何实际的长度约束作用,哪怕你写int arr0[1000],传长度为1的数组进去编译器也不会报错,日常开发不建议使用。
内容的提问来源于stack exchange,提问作者black
相关产品推荐
相关产品推荐

