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

Kaz*_*oom 8 c c++

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

Meh*_*ari 18

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

在C++中,a vector<T>被复制并传递给另一个函数.

  • 这个答案会将数组与指针混淆.这可能听起来很简单,但它确实引起了我认为的混乱.重要的是要保持数组和指针的概念分开,首先要理解它们的根本区别. (4认同)

Bri*_*ndy 11

您可以按值传递数组,但必须先将其包装在结构或类中.或者只是使用类似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]
}
Run Code Online (Sandbox Code Playgroud)

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

int x[10];  
assert(sizeof(x) == 40);
Run Code Online (Sandbox Code Playgroud)

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


Jon*_*eet 8

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

原始答案

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

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

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


Mic*_*urr 5

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

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

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

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

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