More C++ Idioms/循环命名
外观
循环命名
[编辑]意图
[编辑]部分仿真其他语言中的循环标签特性
别名
[编辑]- Labeled loop
- Named loop
动机
[编辑]像 Java,Perl这些语言支持循环的命名,在这些语言中,break和continue关键字可以选择指定一个先前定义的循环标签来控制程序的流程。带标签的break将控制流跳出指定的循环,同样的带标签的continue将在指定的循环处开始下一次迭代。标签允许break 和 continue不只是跳出或继续最内层的循环,而是可以跳出任何外部的带有标签的循环。带有标签的 break 和 continue 能够增加具有嵌套循环的代码可读性和可变性。C++ 中的命名循环原语部分支持这一特性。
解决方案和示例代码
[编辑]命名循环原语用goto来实现。用宏来隐藏goto的显式使用。用下面的代码就可以仿真带标签的break语句:
#define named(blockname) goto blockname; \
blockname##_skip: if (0) \
blockname:
#define break(blockname) goto blockname##_skip;
宏 named(X) 定义了两个 goto 标签 X 和 X_skip。 break 宏只是简单的跳转到 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