为什么C或C ++不允许通过值传递数组来起作用

C和C ++允许按值将结构和对象传递给函数,虽然可以防止按值传递数组,为什么呢?

在C / C ++中,在内部,数组作为指向某个位置的指针传递,基本上,它通过值传递的。 问题是,复制的值表示同一位置的内存地址。

在C ++中, vector被复制并传递给另一个函数。

您可以按值传递数组,但必须先将其包装在结构或类中。 或者只是使用类似std :: vector的类型。

我认为这个决定是出于效率的考虑。 人们不希望大部分时间都这样做。 这与为什么没有无符号双打的原因相同。 没有相关的CPU指令,所以你必须用C ++这样的语言来做很难的事情。

正如@litb所说:“C ++ 1x和boost都将原生数组包装成结构提供了std :: array和boost :: array,我总是喜欢它,因为它允许在结构中传递和返回数组”

数组是指向保存该数组和大小的内存的指针。 请注意,它与指向数组第一个元素的指针不完全相同。

大多数人认为您必须将数组作为指针传递并将大小指定为单独的参数,但这不是必需的。 您可以在保持sizeof()状态的同时传递对实际数组本身的引用。

 //Here you need the size because you have reduced // your array to an int* pointing to the first element. void test1(int *x, int size) { assert(sizeof(x) == 4); } //This function can take in an array of size 10 void test2(int (&x)[10]) { assert(sizeof(x) == 40); } //Same as test2 but by pointer void test3(int (*x)[10]) { assert(sizeof(*x) == 40); //Note to access elements you need to do: (*x)[i] } 

有些人可能会说数组的大小未知。 这不是真的。

 int x[10]; assert(sizeof(x) == 40); 

但是堆上的分配怎么样? 堆上的分配不返回数组。 它们返回一个指向数组第一个元素的指针。 所以新的不是类型安全的。 如果你确实有一个数组变量,那么你就会知道它所拥有的大小。

编辑:我在下面留下了原来的答案,但我相信大部分价值现在都在评论中。 我已经把它作为社区维基,所以如果参与后续对话的任何人想要编辑答案以反映这些信息,请随意。

原始答案

首先,它如何知道要分配多少堆栈? 对于结构和对象来说这是固定的(我相信),但是对于数组,它将取决于数组的大小,直到执行时才知道。 (即使每个调用者在编译时都知道,也可能有不同的调用者具有不同的数组大小。)您可以在参数声明中强制使用特定的数组大小,但这看起来有点奇怪。

除此之外,正如布莱恩所说,这就是效率问题。

你希望通过这一切实现什么目标? 是否需要确保原始数组的内容不会更改?

我认为有三个主要原因导致数组作为指针传递给C而不是值。 其他答案中提到了前两个:

  • 效率
  • 因为一般没有数组的大小信息(如果包含动态分配的数组)

但是,我认为第三个原因是由于:

  • C和早期语言(如B和BCPL)中C的演变,其中数组实际上是作为指向数组数据的指针实现的

Dennis Ritchie谈到了C语言和B语言等C语言的早期演变,特别是如何实现数组以及它们如何受BCPL和B数组的影响以及它们如何以及为何与它们不同(尽管数组中的数组仍然非常相似,因为数组名称会衰减到表达式中的指针)。

我实际上并不知道任何支持按值传递数组的语言。 这样做不会特别有用,并且很快会扼杀调用堆栈。

编辑:对于downvoters – 如果你知道的更好,请让我们都知道。

这是“仅仅因为”答案之一。 C ++从Cinheritance它,并且必须遵循它以保持兼容性。 这样做是为了提高效率。 您很少想要在堆栈上复制一个大型数组(请记住,在这里考虑PDP-11)以将其传递给函数。