我想看看数组和数组引用参数之间的区别,并且得到了重新定义的错误和模棱两可的错误。我不明白为什么编译器无法告诉他们:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
typedef int arrTen[10];
void fun(int arr[]) {
cout << "arr[] called" << endl;
}
void fun(arrTen arr) {
cout << "arrTen called" << endl;
//cout << end(arr) - begin(arr) << endl;
}
void fun(arrTen &arr) {
cout << "arrTen reference called" << endl;
cout << end(arr) - begin(arr) << endl;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
fun(arr); //ambiguous call to overloaded function
return 0;
}
错误消息:
Demo.cpp demo.cpp(24): error C2084: function 'void fun(int [])' already has a body demo.cpp(20): note: see previous definition of 'fun' demo.cpp(37): error C2668: 'fun': ambiguous call to overloaded function demo.cpp(29): note: could be 'void fun(arrTen (&))' demo.cpp(24): note: or 'void fun(int [])' demo.cpp(37): note: while trying to match the argument list '(int [10])'
似乎重新定义了fun(int arr[])
和fun(arrTen arr)
。我不知道为什么数组点参数等于数组参数。
当我注释掉fun(int arr[])
时,fun(arr)
是一个模糊的调用。为什么编译器无法告知我已经传递了对fun
的引用?
当您使用数组语法(带有[]
)声明函数参数时,编译器会将其视为pointer。
即void fun(int arr[])
解析为void fun(int* arr)
。
该数组是由typedef
创建的类型别名,没关系,它仍将被解析为指针。
这意味着采用int []
和arrTen
参数的函数是相同的。
至于模棱两可,两个函数重载(一个使用指针,一个使用对arrTen
的引用)同等有效,并且编译器无法选择要调用的那个。
这两个功能
void fun(int arr[]) {
cout << "arr[] called" << endl;
}
void fun(arrTen arr) {
cout << "arrTen called" << endl;
//cout << end(arr) - begin(arr) << endl;
}
具有与之相同的类型
void fun( int *arr);
因为编译器会隐式调整具有数组类型的参数以指向元素类型的指针。
所以此代码违反了一个定义规则。
为了清楚起见,请考虑这些函数声明
void fun( int arr[100] );
void fun( int arr[10] );
void fun( int arr[1] );
void fun( int arr[] );
void fun( int *arr );
所有它们都声明相同的一个函数,所有这些声明都可以包含在编译单元中,尽管它们是多余的。但是该函数只能有一个定义。
另一方面,编译器也无法在两个通过引用或按值接受参数的函数之间进行选择。
您可以使用一个常数参数制作一个函数,例如
void fun( const arrTen arr) {
cout << "arrTen called" << endl;
//cout << end(arr) - begin(arr) << endl;
}
在这种情况下,将调用通过引用接受参数的函数。
数组会衰减到指针,这就是为什么存在歧义的原因-但您can会收到对10个int
的数组的引用,如下所示:
void fun(int (&arr)[10]) {
std::cout << std::end(arr) - std::begin(arr) << "\n";
}
对于更通用的方法,接受任何类型和大小的数组:
#include <iostream>
#include <iterator>
template<typename T, size_t N>
void fun(T (&arr)[N]) {
std::cout << "called with an array of " << N << " elements\n";
std::cout << std::end(arr) - std::begin(arr) << "\n";
}
int main() {
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
fun(arr);
}
typedef int arrTen[10];
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
arrTen arr1;
return 0;
}
这是arr和arrTen的typeid()的输出
((gdb)p typeid(arr))找不到'int [10]'的typeinfo符号(gdb)p typeid(arr1))找不到'int [10]'的typeinfo符号
这意味着对编译器是相同的,以及为什么您会犯错误