【发布时间】:2012-06-12 22:32:59
【问题描述】:
我读过一篇关于 C++ 中“命名循环成语”的文章:http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Named_Loop
这个成语让我们可以这样写:
named(outer)
for(int i = 0 ; i < rows ; ++i) {
named(inner)
for(int j = 0 ; j < cols ; ++j) {
if(some_condition)
break(outer); // exit the 'outer' loop
}
}
这种结构已经作为许多语言的核心特性存在,例如 Java。
根据文章,可以通过定义两个邪恶宏在C++中实现:
#define named(blockname) goto blockname; \
blockname##_skip: if (0) \
blockname:
#define break(blockname) goto blockname##_skip;
我知道很多人想禁止使用goto。我个人发现它在极少数情况下很有用,尤其是当我想break 一堆嵌套循环时。这个成语在我看来是一个更干净的解决方案,但可以在实际代码中使用它吗?
在文章的讨论页面,可以阅读:
“不要这样做。你会下地狱的”
所以我的问题是:使用命名循环习语有什么缺点?危险吗 ?如果是,为什么?
额外问题:是否可以类似地实现命名continue? (我认为使用named(...) for(...;...;...) {} 语法是不可能的,但谁知道呢?)
编辑:我同意你的观点,重新定义关键字很讨厌。改用#define breakLoop() 怎么样?
【问题讨论】:
-
#define break对我个人来说是个彻底的破坏者。 -
#define break(something) 和#define break 不一样,它不能代替正常的break语句。
-
#define break介于未定义行为和格式错误之间。将它定义为类函数宏并不重要,唯一重要的是宏的名称在词法上与关键字相同。 -
它可以破坏任何东西,因为it is forbidden(至少在使用标准库头文件的源文件中)。
-
如果你想使用
goto,那么就让它保持可见,而不是用宏来掩盖它。