【问题标题】:Range-for-statement cannot build range expression with array function parameterRange-for-statement 无法使用数组函数参数构建范围表达式
【发布时间】:2021-04-20 23:06:46
【问题描述】:

为什么不能构建范围表达式,将数组作为函数参数传递并在范围换语句中使用。 感谢您的帮助

void increment(int v[]){
    // No problem
    int w[10] = {9,8,7,6,5,4,3,2,1,9};
    for(int& x:w){
        std::cout<<"range-for-statement: "<<++x<<"\n";
    }

    // error: cannot build range expression with array function 
    // parameter 'v' since parameter with array type 'int []' is 
    // treated as pointer type 'int *'
    for(int x:v){
        std::cout<<"printing "<<x<<"\n";
    }

    // No problem
    for (int i = 0; i < 10; i++){
        int* p = &v[i];             
    }
}

int main()
{
    int v[10] = {9,8,7,6,5,4,3,2,1,9};
    increment(v);
}

【问题讨论】:

  • 错误已经告诉你出了什么问题。您没有数组函数参数。你有一个指针函数参数。
  • 你们不知道我在学习 C++ 方面付出了哪些努力,因为对我来说一切都是从另一种语言而来的新事物。我认为 SO 适合那些想提供帮助的人,而不是那些认为自己是一切的主人的人。
  • 你在回应我没有提出的论点。我没有声称您没有做出任何努力,我只是声称您的问题显示没有做出任何努力。越清楚你理解困难的部分,任何答案就越合适。一个问题有多好,与它是否是初学者问题无关。 (但无论如何,这将是我在这里的最后评论。这样的讨论也不是 SO 的目的。)

标签: c++


【解决方案1】:

尽管看起来,v 是一个指针而不是一个数组 - 正如错误消息所说。内置数组是个很奇怪的东西,不能复制也不能传值,尴尬的时候会默默变成指针。

没有办法知道它指向的数组的大小,所以没有办法生成一个循环来迭代它。选项包括:

  • 使用适当的范围样式容器,例如std::arraystd::vector
  • 将数组的大小作为额外参数传递,并与老式循环交互

【讨论】:

  • 第三个选项:查看下面 Nikos Athanasiou 的回答。
  • 即使指定了尺寸也很疯狂,例如increment(int v[10]),情况不变
【解决方案2】:

这是因为您将数组传递给函数的方式。正如所写,它衰减为指针。试试

template<int N>
void increment(int (&v)[N])
{
    for (int x : v) std::cout << "printing " << x << "\n";
}

int main()
{
    int v[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 9 };
    increment(v);
}

这个runs 因为在函数中传递了对N 个ints 数组的引用,并且(与指针不同)循环范围可以在这些对象上进行迭代。

【讨论】:

  • 什么将N 传递给增量函数?
  • @JorgeLuque N 是参数类型的一部分,在模板实例化期间推导出来。
【解决方案3】:

函数参数int v[]int * 相匹配

基于范围的 for 语句实际上使用与标准函数 std::beginstd::end 相同的表达式,它们不能在不知道数组大小的情况下为指针定义。它们可以为数组定义,而不是指针。

【讨论】:

  • 基于范围的for语句在遍历数组时不使用std::beginstd::end
  • @hvd 仅用于说明,因为这些函数等价于所需的表达式。
  • 但是 std::beginstd::end 没有被使用的事实仍然是相关的,因为即使你不包含任何标准库头文件,它也允许对数组进行基于范围的 for 循环.
  • "它们只能为数组定义。"不,他们不是。您可以使用vectordeque 等。只要说您可以传递一个数组(不是指针),或者具有beginend 的类的对象成员函数,或对 begin(o)end(o) 有意义的东西(包括 ADL 和 std 命名空间)。
  • @hvd 我更新了我的帖子。现在我认为它更清楚了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多