精简 for 循环.. (C++)

Condensed for loop.. (C++)

我偶然发现了这段代码并试图理解它,某些部分很清楚但不是循环:

forward_list<Class> obj;
auto b_end = obj.before_begin();

for (auto& _ : obj)
    ++b_end ;

obj.insert_after(b_end, Class newObj);

不太确定 for 循环在做什么。有人可以打破 for 循环并帮助我理解它吗?

编辑: 这个问题被标记为重复,但其他线程没有提供足够的信息 and/or 太旧了。

这个:

forward_list<Class> obj;

声明 std::forward_listClass-es 命名为 obj。由于在代码中某处使用了 using namespace std;,因此省略了 std:: 部分。 这个:

auto b_end = obj.before_begin();

定义一个指向 obj 列表中 std::forward_list::before_begin 位置的迭代器。 这个:

for (auto& _ : obj)
    ++b_end;

是一个 range based for loop,它使用通过引用传递的奇怪命名的 _ 变量。在此循环中,b_end 在每次迭代中递增。 最后:

obj.insert_after(b_end, Class newObj);

尝试在 b_end 位置后插入类型为 Class 的新 newObj,但编译失败,因为它可能应该是:

Class newObj;
obj.insert_after(b_end, newObj);

也就是说,_ 只是一个变量名。它是一个(有点不寻常)有效的变量标识符。在这里,_ 变量本身在 for 循环中没有以任何方式使用,因此整个事情可以重写为:

for (auto el : obj){
    ++b_end;
}

auto 关键字代表 auto specifier

std::forward_list 是带有 forward_iterators 的顺序容器。它是一个单边单链表。要将值插入列表,您只能使用方法 insert_after 指定范围 [begin(), end()) 中的迭代器或方法 before_begin().

返回的迭代器

来自 C++ 标准

5 Requires: position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).

因此,如果您要将新值附加到列表的末尾,则必须将迭代器移动到对应于列表中最后一个元素的位置。

所以这个循环命名为 range-based for loop

for (auto& _ : obj)
    ++b_end ;

将迭代器 b_end 逐步移动到列表中最后一个元素所占据的位置。所以现在使用迭代器,您可以使用 insert_after.

方法将新值附加到列表

考虑一个简单的演示程序。

#include <iostream>
#include <forward_list>

int main()
{
    std::forward_list<int> lst = { 1, 2 };

    auto b_end = lst.before_begin();

    for (const auto &_ : lst)
    {
        ++b_end;
        std::cout << *b_end << '\n';
    }
    std::cout << std::endl;

    lst.insert_after(b_end, 3);

    for (const auto &_ : lst) std::cout << _ << ' ';
    std::cout << std::endl;

    return 0;
}

程序输出为

1
2

1 2 3

起初迭代器 b_end 指向列表中第一个元素之前。

    auto b_end = lst.before_begin();
                     ^^^^^^^^^^^^^^

之后在循环中会有两次迭代,因为列表只包含两个元素,迭代器首先会移动到第一个元素对应的位置,然后移动到第二个元素对应的位置。

现在使用获得的迭代器,我们可以在值 2 之后添加值 3。