传递数组作为参考

发布于 2024-12-11 19:48:21 字数 474 浏览 0 评论 0原文

在 C++ 中,当我在编译时不知道大小时,如何传递数组作为引用?到目前为止,我发现让它工作的唯一方法是使用类似的东西

const double( &numbers ) [size]

,但这意味着我需要在编译时知道数组的大小,因此我不能在外部函数。

我的问题是:

  1. 如果我不将数组作为 ( const double( &numbers ) [length] ) 传递,因为例如我不知道它的大小,如何我确保它不会被复制,但它被引用
  2. 如果我像上面的例子一样传递一个数组,( double array[] )它是引用还是复制

In C++ how can I pass an array as a reference when I don't know the size at compile time? So far, I found out that the only way to make it work is to use something like

const double( &numbers ) [size]

but it means that I need to know the size of the array at compile time, thus I cannot use it in an external function.

My questions are:

  1. If I don't pass an array as a ( const double( &numbers ) [length] ), because for example I don't know its size, how do I make sure that it doesn't get copied, but it is referenced?
  2. If I pass an array like in the above example, ( double array[] ) is it referenced or is it copied?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

情魔剑神 2024-12-18 19:48:21

其他答案都很好,但没有人提到使用模板来处理这个问题。您仍然应该让您的函数采用指针和大小,但模板可以自动为您填充:

void f( double const numbers[], std::size_t length )
{ ... }

template< std::size_t Length >
void f( double const (&numbers)[ Length ] )
{
    return f( numbers, Length );
}

The other answers are great, but no one mention using templates to handle this. You should still make your function take a pointer and a size, but templates can fill that automatically for you:

void f( double const numbers[], std::size_t length )
{ ... }

template< std::size_t Length >
void f( double const (&numbers)[ Length ] )
{
    return f( numbers, Length );
}
蓦然回首 2024-12-18 19:48:21

在 C++ 中,您应该使用 std::vector

在 C/C++ 中,不能将数组作为副本传递。数组始终通过引用传递。

编辑

在C++中,通过引用传递的数组具有不同的含义。在 C 和 C++ 中,数组都会衰减为指向数组第一个元素的指针。请检查下面的评论。

In C++, you should use std::vector.

In C/C++, you can't pass arrays as a copy. Arrays are always passed by reference.

EDIT

In C++, arrays passed by reference has different meaning. In both C and C++, arrays decay into a pointer to the first element of the array. Please check the comments below.

清泪尽 2024-12-18 19:48:21

如果我不将数组作为 ( const double( &numbers ) [length] ) 传递,
因为例如我不知道它的大小,我如何确保它
没有被复制,但是被引用了?

是的,这意味着您正在传递一个数组作为引用,

void Foo(const double( &numbers ) [length]);

请注意,长度是一个常量整数。

如果我像上面的例子一样传递一个数组,( double array[] ) 是吗
引用还是复制?

不,它没有被复制。这意味着您正在传递一个指向数组的指针,这相当于,

void Foo(const double *length);

If I don't pass an array as a ( const double( &numbers ) [length] ),
because for example I don't know its size, how do I make sure that it
doesn't get copied, but it is referenced?

Yes, it means you're passing an array as reference,

void Foo(const double( &numbers ) [length]);

Note that the length is a constant integer.

If I pass an array like in the above example, ( double array[] ) is it
referenced or is it copied?

No, it is not copied. It means you're passing a pointer to your array which is equivalent to,

void Foo(const double *length);
小猫一只 2024-12-18 19:48:21

有几件事:

  1. C++ 无论如何都不允许可变大小的数组。因此,所有数组都需要在编译时具有已知的大小。因此,我不完全确定您最初的问题是否适用,因为您首先无法创建大小未知的数组。

  2. 当您传递数组时,它是通过引用完成的。它不会被复制。

无论如何,您可能会考虑使用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;
}

A couple things:

  1. C++ doesn't allow variable-sized arrays anyway. So all your arrays will need to have known sizes at compile time. So I'm not entirely sure if your initial question is even applicable since you won't be able to make an array with an unknown size in the first place.

  2. When you pass an array, it is done by reference. It is not copied.

In any case, you'll probably want to consider using vector instead.

EDIT : See comments.

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;
}
筑梦 2024-12-18 19:48:21

在 C++ 中,数组的名称只是指向其第一个元素的常量指针常量指针意味着一个指针能够改变它所指向的任何东西,但不能改变它指向其他东西。

这意味着每当您传递一个数组时,您实际上是在传递一个常量指针到该数组。换句话说,您已经通过引用传递了它,无需额外的努力。更准确地说,实际上复制的是常量指针,因此最终的(希望不是那么令人困惑的)措辞是您传递一个按值指向数组的常量指针

如果您在编译时不知道数组的大小,只需使用指向数据类型的(普通)指针而不是显式数组。因此,无论 T my_array[] 是什么(其中 T 是一种类型,例如 intdouble 甚至是其中之一你的类)变成 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< /a> 提到)。我只是想进一步阐述这一点。

In C++, an array's name is just a constant pointer to its first element. A constant pointer means a pointer that's capable of changing whatever it points to, but it can't be changed to point to something else.

This means that whenever you pass an array, you're actually passing a constant pointer to that array. In other words, you're already passing it by reference, no need for extra efforts. To be more accurate, what is actually copied is that constant pointer, so the final (hopefully not-that-confusing) phrasing is that you're passing a constant pointer to the array by value.

If you don't know your array's size at compile time, just use a (normal) pointer to your data type instead of an explicit array. So whatever is T my_array[] (where T is a type, like int, double or even one of your classes) becomes T* my_array, and the syntax is exactly the same hereafter... my_array[i] will work fine (another syntax also exists, but not as elegant). For initialization, use the new operator:

T* my_array;

my_array = new T[3];

or

T* my_array;

my_array = new T[x];

where x is an integer (not necessarily constant as is the case with normal arrays). This way you can take this x from the user at runtime and create your "array" then. Just take care not to forget delete[] my_array after you finish using it to avoid memory leaks.

[Final Note] Using such a dynamically allocated array is a good choice only when you know exactly how many elements you want... either at compile time or even at runtime. So, for example, if after the user supplies his x you'll exactly be using those, that's fine. Otherwise you're facing the danger of overflowing your array (if you need more than x) - which usually crashes the application - or just wasting some space. But even if this is the case, you'll implement most of the functions you need for array manipulation yourself. That's why it's preferable to use containers provided by the C++ Standard Library, like std::vector (as Donotalo mentioned). I just wanted to elaborate on that point more.

jJeQQOZ5 2024-12-18 19:48:21

其他语言(例如 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 code> 和 f3 是等效的。

这正是 std::vector 的工作原理。在内部,向量是一个具有两个字段的类:指向第一个元素的指针和向量中元素的数量。当您想要接受任意大小的数组作为参数时,这会使事情变得更简单:

void g(std::vector& v) {...}

Other languages like Java and Python do store the length of arrays at runtime. In C++ arrays, the length of the array is not stored. That means you need to store it manually somewhere.

Whenever you have a fixed size array on your code, the compiler knows the size of the array since it is reading it from the source code itself. But once the code get compiled, that length information is lost. For example:

void f1(double array[10]) {...}

The compiler won't enforce the size of the array. The following code will silently compile since the array parameter of f1 us just a pointer to the first element of an array:

void h1() {
    double a[10];
    double b[5];

    f1(a); // OK.
    f2(b); // Also OK.
}

Since the compiler ignores the static size of the array when passing it to a function, the only way you have to know the size of an arbitrarily sized array passed as a reference is to explicitly state the size:

void f2(double array[], size_t array_size) {...}

Then you can call that function with any array:

void h2() {
    double a[10];
    double b[19];

    f2(a, sizeof(a) / sizeof(a[0]));
    f2(b, sizeof(a) / sizeof(a[0]));
}

The parameter array_size contains the actual size of the array.

As a note, sizeof(array) only works on statically defined arrays. When you pass that array to another functions, the size information is lost.

An array is not the same as a pointer. However, an array of undefined size like the parameter of f2 is just a pointer to the first double element in the sequence:

void f3(double array*, size_t array_size) {...}

For any practicar purpose, f2 and f3 are equivalent.

This is exactly how std::vector works. Internally, a vector is a class with two fields: a pointer to the first element, and the number of elements in the vector. This makes things a little simpler when you want to accept an array of any size as a parameter:

void g(std::vector& v) {...}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文