【问题标题】:Why got error, if not write '&' in the foreach loop?如果在 foreach 循环中没有写“&”,为什么会出错?
【发布时间】:2021-03-03 00:48:09
【问题描述】:

我只是在为我的程序编写一些代码,但最终我忘了写一个小符号并出错,请帮助理解这里出了什么问题。

我想写的代码-

int arr[3][2] = {with some values};
for(auto &i : arr) {
    for(int j : i)
        cout << j << " " ;
    cout << endl;
}

我不小心写的代码-

int arr[3][2] = {with some values};
for(auto i : arr) {   // just forgot to write (&) and got error 
    for(int j : i)
        cout << j << " " ;
    cout << endl;
}

我知道的事情 - 引用 ("&") 运算符使我们能够更改循环内部的值。
但是第二个循环中的错误是什么,我的意思是它可以一个一个地深度复制数组对象,然后创建单独的对象然后迭代它们,尽管我们将无法更改数组值本身。

我遇到了错误 - 'std::end' declared here 1244 | end(const valarray&lt;_Tp&gt;&amp; __va)

【问题讨论】:

  • 您可能遇到了数组指针衰减。指针不能用作基于范围的 for 范围表达式。

标签: c++ arrays loops c++11 foreach


【解决方案1】:

arr 的元素是一个数组 (int[2])。问题是,如果您将i 声明为非引用,它将被推断为int* 类型,数组将衰减为指针并在迭代期间设置为i。指针不能与range-based for loop 一起使用。来自for(int j : i) 的错误消息试图告诉您没有为int* 声明的std::end

如果您将i 声明为引用,它将引用数组 (int(&amp;)[2]),不会发生数组到指针的转换(数组衰减)。

【讨论】:

    【解决方案2】:

    auto i 表示你想要一个值。

    迭代int arr[3][2]得到的值类型是int[3],一个数组。

    由于遗留 C 的原因,无法使用复制构造或赋值来复制原始数组。所以当你这样做时

    auto i = arr[0];
    

    不是int i[2] = arr[0](非法),而是通过一个称为“衰减”的过程获得int* i = arr[0],该过程也继承自C。

    同时,for(auto&amp; i : arr) 复制,它引用子数组。

    简而言之,第一个就是:

    int * i = arr[0];
    

    第二个是

    int(&i)[2] = arr[0];
    

    然后你尝试迭代i

    在第一种情况下,for( int j : i ) 是无稽之谈,因为指针不知道它拥有多少内存。其次,对数组的引用确实知道它持有的内存。所以你可以在第二个中迭代,而不是第一个。


    一般来说,我发现

    for (auto&& i : arr)
    

    成为最干净最通用的迭代方式。有时:

    for (auto const& i : arr)
    

    如果您想声明“我不更改数据”。即使在那里,我更喜欢

    for (auto&& i : std::as_const(arr))
    

    因为它可以处理一些极端情况,例如 vector&lt;bool&gt; 更好。 (遗憾的是,如果 arr 是产生缓冲区的表达式,则 as_const 不能正常工作;引用生命周期延长失败)

    【讨论】:

    • @songyuanyao 当然,听起来不错。抱歉,没有做正确的 C 左右类型解构操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-01
    • 2011-09-12
    • 2015-02-06
    • 2019-01-29
    • 2016-04-23
    • 1970-01-01
    • 2015-12-20
    相关资源
    最近更新 更多