编译错误:在C ++函数内部循环遍历数组的每个元素

时间:2019-01-22 08:57:45

标签: c++

我是C ++的新手,我试图遍历c ++函数中数组的每个元素,但是会出现编译时错误。有人可以解释为什么会这样吗?

这是我的代码:

  @ViewChild(ModalDirective) modal: ModalDirective;

  showModal() {
    this.modal.show();
  }

这是错误消息:

#include <iostream>

int getMax(int arr[])
{
    int max = arr[0];
    for (int x: arr){
        if ( x > max ) max = x;
    }
    return max;
}


int main()
{

    int arr[] = {4,2,5,3,6,8,1};
    int max = getMax(arr);

    std::cout << max << std::endl;

    return 0;
}

4 个答案:

答案 0 :(得分:6)

您必须通过引用传递数组以保留大小信息:

template <std::size_t N>
int getMax(const int (&arr)[N])
{
    int max = arr[0];
    for (int x: arr){
        if ( x > max ) max = x;
    }
    return max;
}

否则必须通过指针传递大小。

int getMax(const int *arr, std::size_t size)
{
    assert(arr != nullptr);
    assert(size != 0);
    return *std::max_element(arr, arr + size);
}

使用std::vector / std::array具有更自然的语法。

int getMax(const std::vector<int>& arr)
{
    assert(!arr.empty());
#if 1
    return *std::max_element(arr.begin(), arr.end());
#else
    int max = arr[0];
    for (int x: arr){
        if ( x > max ) max = x;
    }
    return max;
#endif
}
int main()
{
    const std::vector<int> arr{4,2,5,3,6,8,1};
    const int max = getMax(arr);

    std::cout << max << std::endl;
}

答案 1 :(得分:3)

问题在于,一旦将数组传递给函数,它就不再是数组,而是指向其第一个元素的指针。

当您拥有指向第一个元素的指针时,您将不再拥有有关它指向的数据的任何信息(类型除外)。更重要的是,您对ranged for loop所需的“数组”的 end 一无所知。

简单的解决方案是不使用C风格的纯数组,而使用例如std::array,它将获得有关其大小的信息,并可以在范围for循环中使用。

有一种方法可以使用传递实际数组(或更确切地说是对它的引用)并获取大小,如the answer from Jarod42中所述。


重要说明:即使使用[]声明参数(如int arr[]一样),它也不是数组。如错误消息所示,编译器会将其转换为指针(在您的情况下为int* arr)。

答案 2 :(得分:0)

问题在于您的函数未使用数组。

int getMax(int arr[])  // <-- arr is not an array

将数组作为C ++函数的参数是不可能的。这没有任何意义,这只是C ++历史的一部分。使用std::vector代替数组也是一个很好的理由。

实际上arr是一个指针,您可以在错误消息中看到它

get_max.cpp: In function 'int getMax(int*)':

问题是

for (int x: arr){
如果arr是指针,则

不合法。

您应该做的是将数组的大小传递给函数。像

int getMax(int* arr, size_t size)
{
    int max = arr[0];
    for (size_t i = 0; i < size; ++i ){
        if ( arr[i] > max ) max = arr[i];
    }
    return max;
}

或者使用std::vector

答案 3 :(得分:0)

原始数组作为指针传递,有人说它们在传递给函数时会“衰减”到指针。

int getMax(int arr[])

等同于

int getMax(int* arr)

有些人对单个对象使用后一种语法,前者表示一个函数需要一个数组–仍然只是一个指针(更精确地说:指向数组第一个元素的指针)。

这是原始数组的问题–您不必担心是否使用std::array(通过const(!)引用传递),但是您可能需要从中创建模板函数才能传递任意长度的数组。如果您需要可变长度的数组(或希望避免使用模板),则可以使用std::vector

对于原始数组,您需要将数组长度作为另一个参数传递,然后需要使用经典循环(基于范围的循环不适用于指针):

int getMax(int const arr[], size_t length)
//             ^^^^^ you do not intend to modify the array so pass as const!
{
    int max = *arr;
    ++arr;
    while(--length) // if you didn't use arr[0] before: length--
    {
        if(*arr > max)
            max = *arr;
    }
}

一种变体:向数组传递引用–为了能够使用任意长度,尽管如此,您需要创建以下模板函数:

template <size_t N>
int getMax(int const(&arr)[N]) // ugly syntax, I know...
                               // again: you do not intend, so pass as const
{
    /* now your code works */
}

它是对长度为N的数组的引用,类似地,您可以具有指针:

int(*arr)[N]

如果使用数组的地址,则将得到以下类型:

int a[7];
someFunction(a);       // a decays to pointer: int* (unless reference as above used)
someOtherFunction(&a); // a is passed as pointer to array: int(*)[7]

顺便说一句:您已经在重新发明轮子,因为已经有std::max_element了,尽管您需要将它与迭代器一起使用。指针,尽管完全可以接受,但它也是完全有效的迭代器,对于原始数组,使用最终迭代器有点难看:

int main()
{
    int arr[] = {4,2,5,3,6,8,1};
    int max = *std::max_element
    (
        arr, // decays to pointer
        sizeof(arr)                     /   sizeof(*arr)
        // arr has not yet decayed          ... so you need to devide
        // to pointer so sizeof is          by size of first element
        // OK; but it is size in            to get the number of elements
        // bytes(!)...
    );
    // ...

最后一个问题:您永远不会检查数组长度实际上是否> 0;如果不是,则访问数组超出范围(未定义的行为!):

int max = arr[0]; // (!)

您可以轻松避免这种情况:

int max = std::numeric_limits<int>::min();

唯一的缺点:您无法将空数组与仅包含最小int值的数组区分开。公认的是,无论如何都不会传递空数组,但是使用std :: vector时,机会通常会更大。但是最后,您实际上是安全的,没有任何成本-好吧,(通常)一次选择另一个分支,并对第一个元素进行一次额外的分配...)。