C ++数组是通过引用还是通过指针传递的?

时间:2014-06-05 09:57:44

标签: c++ arrays function pointers reference

在学校,我们的讲师告诉我们,当我们将它传递给一个函数时,整个数组都通过引用传递。

然而,最近我读了一本书。它表示在将整个数组传递给函数时,默认情况下数组通过指针传递。本书进一步提到“通过指针传递非常类似于通过引用传递”,这意味着通过指针传递和通过引用传递实际上是不同的。

看来不同来源的说法不同。

所以我的问题是:在C ++中,当我们将整个数组传递给函数时,是通过引用还是通过指针传递的数组?

例如:

void funcA(int []); //Function Declaration

int main()
{
    int array[5];
    funcA(array); //Is array passed by ref or by pointer here?
}

3 个答案:

答案 0 :(得分:12)

最糟糕的是,你的讲师错了。充其量,他正在简化术语,并在此过程中让您感到困惑。不幸的是,这在软件教育中相当普遍。事实是,很多书也错了;数组不是"传递"根本不是"指针"或"参考"。

事实上,由于旧的C限制,数组无法通过值传递,因此数组作为函数参数会发生一些特殊的魔法。

函数声明:

void funcA(int[]);

默默地翻译成以下内容:

void funcA(int*);

当你写这篇文章时:

funcA(myArray);

它被默默地翻译成以下内容:

funcA(&myArray[0]);

结果是你根本没有传递数组; 您将指针传递给其第一个元素

现在,在某些抽象/简化级别,你可以调用这个"通过指针传递数组","通过引用传递一个数组"甚至"将句柄传递给数组",但如果你想用C ++术语说话,那些短语都不准确。

答案 1 :(得分:3)

您的讲师使用的术语令人困惑。但是,在函数声明中,例如

void funcA(int []);

int[]只是说int*的另一种方式。因此funcA可以接受任何或可以转换为int*的参数。

数组可以衰减到指向右上下文中第一个元素的指针。这意味着,例如,您可以将数组的名称分配给指针,如下所示:

int array[42];  // array is of type int[42]
int * arr = array; // array decays to int*

因此,当您将array传递给funcA时,

funcA(array); // array decays to int*

funcA有一个指向数组第一个元素的指针。

但也可以通过引用传递数组。它只需要不同的语法。例如

void funcB(int (&arr)[42]);

因此,在您的示例中,由于函数funcA的签名,您将传递指向数组的第一个元素的指针。如果您致电funcB(array),则会传递参考。

答案 2 :(得分:1)

传递指针有点用词不当。它并不是在C ++中发生的。只有按值传递和传递引用。特别是指针通过值传递。

您的问题的答案是:取决于

考虑以下签名:

void foo(int *arr);
void bar(int *&arr);
void baz(int * const &arr);
void quux(int (&arr)[42]);

假设您将数组传递给其中每个函数:

  • 在foo(arr)中,您的数组会衰减为指针,然后按值传递。
  • 在bar(arr)中,这是一个编译错误,因为你的数组会衰减为(临时)指针,并且这将通过引用传递。这几乎总是一个bug,因为你想要一个可变引用的原因是改变引用的值,而不会发生什么(你会改变临时值)。我添加这个,因为这实际上适用于某些编译器(MSVC ++)并启用了特定的扩展。如果你反而手动衰减指针,那么你可以改为传递它(例如int *p = arr; bar(p);
  • 在baz(arr)中,你的数组衰减到一个临时指针,它由(const)引用传递。
  • 在quux(arr)中,您的数组通过引用传递。

你的书与他们相似的意思是,按值传递指针并传递引用通常是相同的。区别仅在于C ++级别:使用引用时,您没有指针的值(因此无法更改它),并且保证引用实际对象(除非您之前中断了程序)。 / p>