for
循环
来自 cppreference.cn
有条件地重复执行语句,其中语句不需要管理循环条件。
内容 |
[编辑] 语法
attr (可选) for ( init-statement condition (可选) ; expression (可选) ) statement |
|||||||||
attr | - | (自 C++11 起) 任意数量的 属性 | ||
init-statement | - | 下列之一
注意任何 init-statement 必须以分号结尾。这就是为什么它通常被非正式地描述为表达式或后跟分号的声明。 | ||
condition | - | 条件 | ||
expression | - | 表达式(通常是递增循环计数器的表达式) | ||
statement | - | 语句(通常是复合语句) |
[编辑] 条件
|
(自 C++26 起) |
- 如果它可以被语法解析为表达式,则它被视为表达式。否则,它被视为不是结构化绑定声明的声明(自 C++26 起)。
当控制到达 condition 时,condition 将产生一个值,该值用于确定是否将执行 statement。
[编辑] 表达式
如果 condition 是表达式,则它产生的值是上下文转换为 bool 的表达式的值。如果该转换是非良构的,则程序是非良构的。
[编辑] 声明
如果 condition 是简单声明,则它产生的值是上下文转换为 bool 的决策变量(见下文)的值。如果该转换是非良构的,则程序是非良构的。
[编辑] 非结构化绑定声明
声明具有以下限制
- 语法上符合以下形式
|
(C++11 前) |
|
(自 C++11 起) |
声明的决策变量是声明的变量。
结构化绑定声明声明具有以下限制 声明的决策变量是由声明引入的虚构变量 e。 |
(自 C++26 起) |
[编辑] 解释
一个 for 语句等价于
{
|
|||||||||
expression ;
- 例外在于
- init-statement 的作用域和 condition 的作用域相同。
- statement 的作用域和 expression 的作用域是不相交的,并且嵌套在 init-statement 和 condition 的作用域内。
- 在 statement 中执行 continue 语句 将会求值 expression。
空的 condition 等价于 true。
如果需要在 statement 内终止循环,则可以使用 break 语句 作为终止语句。
如果需要在 statement 内终止当前迭代,则可以使用 continue 语句 作为快捷方式。
[编辑] 注解
for (;;) int n; // n goes out of scope
与 while
循环的情况一样,如果 statement 不是复合语句,则其中声明的变量的作用域被限制为循环体,如同它是复合语句一样。
作为 C++ 前向进度保证 的一部分,如果一个循环(不是平凡无限循环)(自 C++26 起)在没有可观察行为的情况下不终止,则行为是未定义的。编译器被允许移除此类循环。
for (int i = 0;;) { long i = 1; // valid C, invalid C++ // ... }
虽然在 C 语言中,在 init-statement 和 condition 的作用域中声明的名称可以在 statement 的作用域中被遮蔽,但在 C++ 中这是被禁止的。
[编辑] 关键字
[编辑] 示例
#include <iostream> #include <vector> int main() { std::cout << "1) typical loop with a single statement as the body:\n"; for (int i = 0; i < 10; ++i) std::cout << i << ' '; std::cout << "\n\n" "2) init-statement can declare multiple names, as\n" "long as they can use the same decl-specifier-seq:\n"; for (int i = 0, *p = &i; i < 9; i += 2) std::cout << i << ':' << *p << ' '; std::cout << "\n\n" "3) condition may be a declaration:\n"; char cstr[] = "Hello"; for (int n = 0; char c = cstr[n]; ++n) std::cout << c; std::cout << "\n\n" "4) init-statement can use the auto type specifier:\n"; std::vector<int> v = {3, 1, 4, 1, 5, 9}; for (auto iter = v.begin(); iter != v.end(); ++iter) std::cout << *iter << ' '; std::cout << "\n\n" "5) init-statement can be an expression:\n"; int n = 0; for (std::cout << "Loop start\n"; std::cout << "Loop test\n"; std::cout << "Iteration " << ++n << '\n') { if (n > 1) break; } std::cout << "\n" "6) constructors and destructors of objects created\n" "in the loop's body are called per each iteration:\n"; struct S { S(int x, int y) { std::cout << "S::S(" << x << ", " << y << "); "; } ~S() { std::cout << "S::~S()\n"; } }; for (int i{0}, j{5}; i < j; ++i, --j) S s{i, j}; std::cout << "\n" "7) init-statement can use structured bindings:\n"; long arr[]{1, 3, 7}; for (auto [i, j, k] = arr; i + j < k; ++i) std::cout << i + j << ' '; std::cout << '\n'; }
运行此代码
1) typical loop with a single statement as the body: 0 1 2 3 4 5 6 7 8 9 2) init-statement can declare multiple names, as long as they can use the same decl-specifier-seq: 0:0 2:2 4:4 6:6 8:8 3) condition may be a declaration: Hello 4) init-statement can use the auto type specifier: 3 1 4 1 5 9 5) init-statement can be an expression: Loop start Loop test Iteration 1 Loop test Iteration 2 Loop test 6) constructors and destructors of objects created in the loop's body are called per each iteration: S::S(0, 5); S::~S() S::S(1, 4); S::~S() S::S(2, 3); S::~S() 7) init-statement can use structured bindings: 4 5 6
输出
[编辑] 参见 | 范围 for 循环(C++11 起) |
在范围内执行循环
|