考虑一下这段代码(VS2008):
void WordManager::formatWords(std::string const& document) { document_ = document; unsigned int currentLineNo = 1; size_t oldEndOfLine = 0; size_t endOfLine = document_.find('\n'); while(endOfLine != std::string::npos) { std::string line = document_.substr(oldEndOfLine,(endOfLine - oldEndOfLine)); if(line.size() < 2) { oldEndOfLine = endOfLine + 1; endOfLine = document_.find('\n',oldEndOfLine); continue; } std::vector<std::string> words = Utility::split(line); for(unsigned int i(0); i < words.size(); ++i) { if(words[i].size() < 2) continue; Utility::trim(words[i],WordManager::delims); Utility::normalize(words[i],WordManager::replace,WordManager::replaceWith); if(ruleOne(words[i]) && ruleTwo(words[i])) { std::set<Word>::iterator sWIter(words_.find(Word(words[i]))); if(sWIter == words_.end()) words_.insert(Word(words[i])).first->addLineNo(currentLineNo); else sWIter->addLineNo(currentLineNo); } } ++currentLineNo; oldEndOfLine = endOfLine + 1; endOfLine = document_.find('\n',oldEndOfLine); } }
如果它很重要:这是来自用于过滤和修改文档中的单词的家庭作业的代码.文档保存文档(以前从文件中读取)
我想介绍一个恶意的goto,因为我认为它在这种情况下实际上更清洁:
void WordManager::formatWords(std::string const& document) { document_ = document; unsigned int currentLineNo = 1; size_t oldEndOfLine = 0; size_t endOfLine = document_.find('\n'); while(endOfLine != std::string::npos) { std::string line = document_.substr(oldEndOfLine,(endOfLine - oldEndOfLine)); // HERE!!!!!! if(line.size() < 2) goto SkipAndRestart; std::vector<std::string> words = Utility::split(line); for(unsigned int i(0); i < words.size(); ++i) { if(words[i].size() < 2) continue; Utility::trim(words[i],WordManager::replaceWith); if(ruleOne(words[i]) && ruleTwo(words[i])) { std::set<Word>::iterator sWIter(words_.find(Word(words[i]))); if(sWIter == words_.end()) words_.insert(Word(words[i])).first->addLineNo(currentLineNo); else sWIter->addLineNo(currentLineNo); } } SkipAndRestart: ++currentLineNo; oldEndOfLine = endOfLine + 1; endOfLine = document_.find('\n',oldEndOfLine); } }
目前这是否是一个好的设计选择是无关紧要的.编译器抱怨错误C2362:’goto SkipAndRestart’跳过’words’的初始化
我不明白这个错误.为什么跳过单词初始化很重要,也是错误的?这正是我想要发生的事情,我不希望它做更多工作,只需重新启动血腥循环.继续宏不是或多或少完全相同吗?
解决方法
你正在跳过单词数组的构造:
if(line.size() < 2) goto SkipAndRestart; std::vector<std::string> words = Utility::split(line); // ... SkipAndRestart:
您可以在SkipAndRestart:标签之后使用单词,这可能是个问题.你不要在你的情况下使用它,但是单词变量在引入它的作用域结束之前不会被破坏,所以就编译器而言,变量仍在使用中.标签.
你可以通过在自己的范围内放置单词来避免这种情况:
if(line.size() < 2) goto SkipAndRestart; { std::vector<std::string> words = Utility::split(line); // ... } SkipAndRestart:
请注意,continue语句跳转到循环的末尾,在实际上无法放置标签的位置.这是在循环内部任何局部变量被破坏之后,但在跳回到循环顶部之前的一个点.