对函数的重新定义和模糊调用具有数组参数

问题描述 投票:1回答:4

我想看看数组和数组引用参数之间的区别,并且得到了重新定义的错误和模棱两可的错误。我不明白为什么编译器无法告诉他们:

#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])'
  1. 似乎重新定义了fun(int arr[])fun(arrTen arr)。我不知道为什么数组点参数等于数组参数。

  2. 当我注释掉fun(int arr[])时,fun(arr)是一个模糊的调用。为什么编译器无法告知我已经传递了对fun的引用?

c++ arrays parameter-passing
4个回答
2
投票

当您使用数组语法(带有[])声明函数参数时,编译器会将其视为pointer

void fun(int arr[])解析为void fun(int* arr)

该数组是由typedef创建的类型别名,没关系,它仍将被解析为指针。

这意味着采用int []arrTen参数的函数是相同的。


至于模棱两可,两个函数重载(一个使用指针,一个使用对arrTen的引用)同等有效,并且编译器无法选择要调用的那个。


1
投票

这两个功能

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;
}

在这种情况下,将调用通过引用接受参数的函数。


1
投票

数组会衰减到指针,这就是为什么存在歧义的原因-但您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);
}

0
投票
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符号

这意味着对编译器是相同的,以及为什么您会犯错误

© www.soinside.com 2019 - 2024. All rights reserved.