为什么C或C ++不允许将值按数组传递给函数?

问题描述 投票:9回答:6

C和C ++允许按值将结构和对象传递给函数,尽管可以防止按值传递数组。

为什么?

c++ c arrays function parameter-passing
6个回答
18
投票

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

顺便说一下,在C ++中,vector<T>被复制并传递给另一个函数。

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

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

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

但是堆上的分配呢?堆上的分配不会返回数组。它们返回一个指向数组第一个元素的指针。因此,new不是类型安全的。如果确实有一个数组变量,那么您将知道该变量的大小。     

8
投票
编辑:我已经在下面留下了原始答案,但是我认为大部分价值现在都在注释中。我已将其设置为社区Wiki,因此,如果参与后续对话的任何人都想编辑答案以反映该信息,请放心。

原始答案

一方面,它怎么知道要分配多少堆栈?这对于结构和对象是固定的(我相信),但是对于数组,它取决于数组的大小,直到执行时才知道。 (即使每个调用者在编译时都知道,可能会有不同的调用者使用不同的数组大小。)您可以在参数声明中强制使用特定的数组大小,但这似乎有些奇怪。

此外,正如Brian所说,还有效率问题。

您想通过所有这些实现什么?是否要确保不更改原始数组的内容?


4
投票
我认为,将数组作为指针传递给C而不是按值传递的主要原因有3个。其他答案中提到了前2个:

    效率
  • 因为通常没有数组的大小信息(如果您包括动态分配的数组)
  • 但是,我认为第三个原因是:

      C从早期的语言(如B和BCPL,其中数组实际上被实现为指向数组数据的指针的演变)>>
  • [Dennis Ritchie谈论了C从诸如BCPL和B的语言的早期演变,特别是数组的实现方式以及它们如何受到BCPL和B数组的影响以及它们如何以及为何不同的原因(同时由于数组而在表达式中保持非常相似)名称会衰减为表达式中的指针。


  • 3
    投票
    我实际上不了解支持通过值传递

    naked


    3
    投票
    这是“仅因为”答案之一。 C ++从C继承了它,必须遵循它以保持兼容性。在C中这样做是为了提高效率。您很少会想在堆栈上复制一个大数组(请记住,这里以为PDP-11)以将其传递给函数。
    © www.soinside.com 2019 - 2024. All rights reserved.