跳转到内容

More C++ Idioms/循环命名

维基教科书,自由的教学读本

循环命名

[编辑]

意图

[编辑]

部分仿真其他语言中的循环标签特性

别名

[编辑]
  • Labeled loop
  • Named loop

动机

[编辑]

像 Java,Perl这些语言支持循环的命名,在这些语言中,breakcontinue关键字可以选择指定一个先前定义的循环标签来控制程序的流程。带标签的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 标签 XX_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

已知应用

[编辑]

相关原语

[编辑]

参考资料

[编辑]