在C ++中,当我在编译时不知道大小时,如何将数组作为参考传递?到目前为止,我发现使其工作的唯一方法是使用类似
的东西const double( &numbers ) [size]
但这意味着我需要在编译时知道数组的大小,因此我无法在外部函数中使用它。
我的问题是:
( const double( &numbers ) [length] )
传递,因为例如我不知道它的大小,如何确保它不会被复制,但引用?( double array[] )
是引用还是复制?答案 0 :(得分:6)
在C ++中,您应该使用std::vector。
在C / C ++中,您无法将数组作为副本传递。数组总是通过引用传递。
修改强>
在C ++中,通过引用传递的数组具有不同的含义。在C和C ++中,数组衰减成指向数组第一个元素的指针。请查看以下评论。
答案 1 :(得分:6)
其他答案很棒,但没有人提到使用模板来处理这个问题。您仍然应该使您的函数采用指针和大小,但模板可以自动为您填充:
void f( double const numbers[], std::size_t length )
{ ... }
template< std::size_t Length >
void f( double const (&numbers)[ Length ] )
{
return f( numbers, Length );
}
答案 2 :(得分:2)
一些事情:
C ++不允许使用可变大小的数组。因此,所有数组在编译时都需要具有已知的大小。因此,我不能完全确定您的初始问题是否适用,因为您无法首先制作出尺寸未知的阵列。
传递数组时,它是通过引用完成的。它没有被复制。
在任何情况下,您可能都希望考虑使用vector
。
编辑:见评论。
double average(const double *arr, size_t len){
// Compute average
return accumulate(arr, arr + len, 0) / (double)len;
}
int main(){
double array[10] = // Initialize it
cout << average(array, 10) << endl;
// Alternatively: This could probably be made a macro.
// But be careful though since the function can still take a pointer instead
// of an array.
cout << average(array, sizeof(array) / sizeof(double)) << endl;
return 0;
}
答案 3 :(得分:2)
在C ++中,数组的名称只是第一个元素的常量指针。 常量指针表示能够改变指向的指针,但不能将其更改为指向其他指针。
这意味着无论何时传递数组,实际上都是将常量指针传递给该数组。换句话说,你已经通过引用传递它,不需要额外的努力。为了更准确,实际上复制的是常量指针,所以最后(希望不那么令人困惑)的措辞就是你传递了一个按值到数组的常量指针。
如果在编译时不知道数组的大小,只需使用指向数据类型的(普通)指针而不是显式数组。所以无论T my_array[]
是什么(其中T
是一个类型,如int
,double
甚至是你的一个类,都变为T* my_array
,语法正是如此以下相同... my_array[i]
将正常工作(另一种语法也存在,但不是很优雅)。要进行初始化,请使用new
运算符:
T* my_array;
my_array = new T[3];
或
T* my_array;
my_array = new T[x];
其中x
是一个整数(不一定是常规数组的情况)。这样,您可以在运行时从用户处获取此x
,然后创建“数组”。完成使用后,请注意不要忘记delete[] my_array
以避免内存泄漏。
[最终注意事项]只有在编译时或甚至在运行时确切地知道所需的元素数量时,才使用这样的动态分配的数组是一个不错的选择。因此,举例来说,如果在用户提供他的x
后你将完全使用它们,那就没问题。否则,您将面临数据溢出的危险(如果您需要超过x
) - 这通常会导致应用程序崩溃 - 或者只是浪费一些空间。但即使是这种情况,您也可以自己实现阵列操作所需的大部分功能。这就是为什么最好使用C ++标准库提供的容器,比如std::vector
(如Donotalo提到的那样)。我只是想详细说明这一点。
答案 4 :(得分:2)
如果我没有将数组作为(const double(&amp; numbers)[length])传递, 因为例如我不知道它的大小,我该如何确定它 不会被复制,但它被引用?
是的,这意味着你要传递一个数组作为参考,
void Foo(const double( &numbers ) [length]);
请注意,length
是一个常数整数。
如果我像上面的例子一样传递一个数组,那么(double array [])就是它 引用或被复制?
不,它没有被复制。这意味着你传递一个指向你的数组的指针,它等同于
void Foo(const double *length);
答案 5 :(得分:0)
Java和Python等其他语言会在运行时存储数组的长度。在C ++数组中,不存储数组的长度。这意味着您需要在某处手动存储它。
每当你的代码上有一个固定大小的数组时,编译器就会知道数组的大小,因为它是从源代码本身读取的。但是一旦代码被编译,那长度信息就会丢失。例如:
void f1(double array[10]) {...}
编译器不会强制执行数组的大小。以下代码将静默编译,因为f1
的数组参数只是指向数组第一个元素的指针:
void h1() {
double a[10];
double b[5];
f1(a); // OK.
f2(b); // Also OK.
}
由于编译器在将数组传递给函数时忽略了数组的静态大小,因此您必须知道作为引用传递的任意大小数组的大小的唯一方法是显式声明大小:
void f2(double array[], size_t array_size) {...}
然后你可以用任何数组调用该函数:
void h2() {
double a[10];
double b[19];
f2(a, sizeof(a) / sizeof(a[0]));
f2(b, sizeof(a) / sizeof(a[0]));
}
参数array_size
包含数组的实际大小。
作为注释,sizeof(array)
仅适用于静态定义的数组。将该数组传递给另一个函数时,大小信息将丢失。
数组与指针不同。但是,像f2
参数这样的未定义大小数组只是指向序列中第一个double
元素的指针:
void f3(double array*, size_t array_size) {...}
出于任何实际目的,f2
和f3
是等效的。
这正是std::vector
的工作原理。在内部,向量是一个具有两个字段的类:指向第一个元素的指针,以及向量中的元素数。当你想接受任何大小的数组作为参数时,这会使事情变得更简单:
void g(std::vector& v) {...}