【发布时间】:2011-02-21 12:08:21
【问题描述】:
- 我能否像处理 int 和 bool 等基元一样将数组传递给函数?
- 我可以按值传递它们吗?
- 函数如何知道它所传递的数组的大小?
【问题讨论】:
【问题讨论】:
您可以按值传递std::vector 和类似的精心设计的对象(尽管这并不常见)。通常,您通过引用或 const 引用传递。
一个 C/C++ 数组,如
void foo(int x[])
总是通过引用传递。此外,该函数无法确定调用者传入的参数的真实大小,您必须假设一个大小(或将其作为单独的参数传递)。
【讨论】:
void f(int a[]); 并这样称呼它:int myArr[size]; f(myArr);
【讨论】:
void foo( int (&a)[10] )
我可以将数组传递给函数吗? 我会使用诸如 int 之类的原语 和布尔?
是的,但只能使用指针(即:通过引用)。
我可以按值传递它们吗?
没有。您可以创建支持该功能的类,但普通数组不支持。
函数如何知道它传递的数组的大小?
它没有。这就是使用 vector<T> 之类的东西而不是 T * 的原因。
澄清
一个函数可以获取一个特定大小的数组的引用或指针:
void func(char (*p)[13])
{
for (int n = 0; n < 13; ++n)
printf("%c", (*p)[n]);
}
int main()
{
char a[13] = "hello, world";
func(&a);
char b[5] = "oops";
// next line won't compile
// func(&b);
return 0;
}
不过,我很确定这不是 OP 想要的。
【讨论】:
void foo( int (&a)[10] ) 将通过引用接收正好 10 个整数的数组。动态分配数组的问题稍微复杂一点...new int[10] 的类型是int *,而不是int [10],但是您可以动态创建一个包含 10 个整数的数组:int (*p)[10] = new int[1][10];,然后调用前面的函数:foo(*p).
您可以按照 C 的常用方式传递数组(数组衰减为指针),或者您可以通过引用传递它们,但它们不能通过值传递。对于第二种方法,它们会随身携带它们的尺寸:
template <std::size_t size>
void fun( int (&arr)[size] )
{
for(std::size_t i = 0; i < size; ++i) /* do something with arr[i] */ ;
}
大多数时候,除非您特别需要原生数组,否则在标准库中使用 std::vector 或其他序列会更优雅。
【讨论】:
const 的非模板版本)。您无法从 arr 本身获得大小,我认为您当前的措辞有点误导。
const,唯一的区别是它可以在与签名中定义的大小完全相同的数组中工作:void foo( int (&a)[3] ) 将只接受 3 个整数的数组。跨度>
int N=10; void fun( int (&arr)[N] ) {} 编译。是我做错了什么还是我们的目的不同?
是的,您可以像原始类型一样传递它们。 是的,如果您真的想使用一些包装代码,您可以按值传递,但您可能不应该这样做。 它将函数原型的大小作为长度——它可能匹配也可能不匹配传入的数据——所以不,它真的不知道。
或者!
将引用或 const 引用传递给向量,这样更安全,而且大小信息触手可及。
【讨论】:
你可以传递一个数组,但如果你想确定它,你必须传递它的大小:
function(array, size);
数组总是通过引用传递,函数可以写成以下两种方式之一:
Declaration: void function (class*, int);
Implementation: void function(class array[]; int size) {}
或
Declaration: void function (class*, int);
Implementation: void function(class *array; int size) {}
当您将数组传递给函数时,函数实质上会接收指向该数组的指针,如上面的第二个示例所示。这两个示例将完成相同的事情。
【讨论】:
我可以将数组传递给函数吗? 我会使用诸如 int 之类的原语 和布尔?
是的,你可以。将数组名称作为参数传递给函数会传递第一个元素的地址。
简而言之:
void foo(int a[]);
等价于
void foo(int * a);
我可以按值传递它们吗?
不是真的。与数组名称一起传递的“值”是第一个元素的地址。
传递 C 样式数组副本的唯一方法是将其包装在实现深拷贝语义的 class 或 struct 中。
函数如何知道大小 它传递的数组是什么?
它不会,除非你让你的函数接受一个额外的参数,即数组的大小。
【讨论】:
int a[] 和 int * b 之间的等价性:但有一个区别:第一种形式不允许您使用指针(例如,a++ 是非法的)。跨度>
a++ - 它们是完全等价的。 @John,不过,“没有办法接受或传递 C 样式数组的副本”是错误的。如果将数组包装到结构中并按值获取结构,则包装的数组被复制,并且函数接收 c 样式数组的副本。
void bar( int a[] ) { ++a; *a = 7; } 在 g++ 和 comeau 中编译。
C 风格的数组在传递给函数时表现得非常奇怪。对于固定大小的数组,我会推荐std::array<int, 10>,它可以像内置类型一样按值传递。对于可变大小的数组,我推荐std::vector<int>,正如其他答案中所建议的那样。
【讨论】: