更多 C++ 习语/命名循环
外观
部分模拟其他语言中找到的标记循环功能。
标记循环
一些语言,如 Java 和 Perl,支持标记循环结构。在这些语言中,break 和 continue 关键字可以选择指定先前定义的循环标签来控制程序的流程。标记中断将控制流从指定的循环中带出,类似地,标记继续从下一次迭代开始。标签允许中断和继续不仅是最内层的循环,而且任何带有标签的外部循环。标记中断和继续可以提高使用嵌套循环的复杂代码的可读性和灵活性。C++ 中的命名循环习语为该功能提供了部分支持。
命名循环习语使用 goto 实现。宏用于隐藏 goto 的显式使用,这通常是被人不齿的。只有标记中断语句可以使用以下两个参数化宏来模拟。
#define named(blockname) goto blockname; \
blockname##_skip: if (0) \
blockname:
#define break(blockname) goto blockname##_skip
named(X) 宏定义了两个 goto 标签 X 和 X_skip。break 宏是一个简单的 goto 到 X_skip 标签。示例如下。
struct test
{
std::string str;
test (std::string s) : str(s) {
std::cout << "test::test()::" << str << "\n";
}
~test () {
std::cout << "~test::" << str << "\n";
}
};
int main(void)
{
named (outer)
for (int i = 0; i < 10; i++)
{
test t1("t1");
int j = 0;
named(inner)
for (test t2("t2"); j < 5; j++)
{
test t3("t3");
if (j == 1) break(outer);
if (j == 3) break(inner);
test t4("t4");
}
std::cout << "after inner\n";
}
return 0;
}
goto 不影响对象的正确构造和销毁,如上述程序的输出所证实。
test::test()::t1
test::test()::t2
test::test()::t3
test::test()::t4
~test::t4
~test::t3
test::test()::t3
~test::t3
~test::t2
~test::t1