精简 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_list 个 Class
-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。
我偶然发现了这段代码并试图理解它,某些部分很清楚但不是循环:
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_list 个 Class
-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。