繁体   English   中英

为什么数组的大小通过C ++编译器已知的引用传递给函数?

[英]Why is the size of an array passed to a function by reference known to the compiler in C++?

我知道当我想将一个数组传递给一个函数时,它会衰减成指针,因此它的大小将不会被知道,这两个声明是等价的:

void funtion(int *tab, int size);

void funtion(int tab[], int size);

我理解为什么。 但是,当我传递一个数组作为参考时,我检查过:

void funtion(int (&tab)[4]);

编译器将知道数组的大小,并且不允许我传递不同大小的数组作为此函数的参数。

这是为什么? 我知道当我按地址传递数组时,在计算数组中第i个元素的位置时不会考虑大小,所以即使我在函数声明中明确地包含它,它也会被丢弃:

void funtion(int tab[4], int size);

但是当我通过引用传递数组时有什么不同? 为什么编译器知道它的大小?

注意:我对编译时已知大小的数组感兴趣,所以我没有使用任何模板。

我在Stack Overflow上发现了类似的问题 ,但它没有回答我的问题 - 它没有解释为什么编译器知道数组的大小,只有一些关于如何将数组传递给函数的信息。

因为它可以,并且因为检查增加了额外的安全性。 编译器知道数组的大小,因为你告诉它,就在函数声明中。 既然该信息可用,为什么不用它来表示源代码中的错误?

真正的问题是为什么你的最后一个例子不会做同样的检查。 不幸的是,这是C遗留的另一部分 - 你永远不会传递一个数组,它总是衰变成一个指针。 然后数组的大小变得无关紧要。

可以添加支票吗? 可能,但它的用途有限(因为我们现在都使用std :: array - 对!?),因为它无疑会打破一些代码。 这个,例如:

void func (char Values [4]);
func ("x");

这是合法的,但不会额外检查数组大小。

因为在这种情况下编译器没有提交奇怪的隐式类型更改。 通常当你写:

void func(int[4]);

要么

void func(void());

编译器决定“帮助”您并将其转换为:

void func(int *);

要么

void func(void(*)());

有趣的是 - 当你尝试归还其中一个时,它不会以这种方式帮助你。 试着写:

int func()[4], func1()();

哎呀 - 惊喜 - 编译错误。

否则,数组是数组,并且具有常量大小,可以使用sizeof运算符获取。

然而,这经常被遗忘,因为上面提到的编译器行为,并且还因为在不期望这种情况时应用于数组类型的对象的隐式指针转换。 这经常是这样。 虽然这里没有应用隐式数组对象转换的少数例外:

size_t arr[4], 

    (*parr)[3] = &arr, //taking the address of array

    (&refarr)[3] = arr, //storing reference to array

    sizearrobject = sizeof(arr); //taking the array object size

由于第二行和第三行上的类型不兼容,上述示例将触发编译器错误。

我在谈论arr对象没有自动转换为这样的情况:

(size_t*)&arr

好吧,有几种方法可以传递一个数组来运行。 您可以通过引用将指针传递给它,并且有两种方法可以定义或不明确地定义它的大小。


在您的问题中,您可以比较这两种方式:

  • 指向第一个元素的指针: void f(int *arr)
  • 引用整个数组: void f(int (&arr)[size])

您问为什么只需要在其中一种情况下指定大小。

看起来你假设它们之间的唯一区别是一个使用指针而另一个使用引用。 但是这个语句是不正确的,它们有更多的区别:一个是指向第一个元素的指针,第二个是对整个数组的引用。


您可以通过指针将数组传递给整个数组:

 void f(int (*arr)[size]) 

将它与您的示例进行比较,将refence传递给整个数组:

void f(int &arr)

它们是相似的,它们具有相似的语法,它们都明确地定义了数组大小。


另外,考虑一下:

 void f(int &arr) 

它看起来像通过引用传递单个int,但您可以传递一个未知大小的数组。

指针替代它

 void f(int *arr) 

您问为什么只需要在其中一种情况下指定数组大小。 这是因为你使用的语法,不是因为一个是指针而另一个是引用。

正如我所说,你可以使用指针或引用。 您可以指定数组大小,也可以允许使用任何大小的数组。 这两个没有连接。

 // by pointer by reference /* Any size */ void f(int *arr) void f(int &arr) /* Specific size */ void f(int (*arr)[x]) void f(int (&arr)[x]) 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM