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