假设我有以下功能:
// Precondition: foo is '0' or 'MAGIC_NUMBER_4711'
// Returns: -1 if foo is '0'
// 1 if foo is 'MAGIC_NUMBER_4711'
int transmogrify(int foo) {
if (foo == 0) {
return -1;
} else if (foo == MAGIC_NUMBER_4711) {
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨"缺少return语句",但我知道foo永远不会有0或不同的值MAGIC_NUMBER_4711,否则我的函数将没有定义的语义.
对此更好的解决方案是什么?这真的是一个问题,即标准说的是什么?
有时,您的编译器无法推断出您的函数实际上没有丢失的返回.在这种情况下,存在几种解决方案:
假设以下简化代码(虽然现代编译器将看到没有路径泄漏,只是示例):
if (foo == 0) {
return bar;
} else {
return frob;
}
Run Code Online (Sandbox Code Playgroud)
if (foo == 0) {
return bar;
}
return frob;
Run Code Online (Sandbox Code Playgroud)
如果您可以将if语句解释为一种防火墙或前提条件,则此方法很有用.
if (foo == 0) {
return bar;
} else {
return frob;
}
abort(); return -1; // unreachable
Run Code Online (Sandbox Code Playgroud)
相应地返回其他内容.评论告诉其他程序员和你自己为什么会这样.
#include <stdexcept>
if (foo == 0) {
return bar;
} else {
return frob;
}
throw std::runtime_error ("impossible");
Run Code Online (Sandbox Code Playgroud)
有些人会回归到单功能返回,即单功能退出点作为解决方法.这可能在C++中被视为过时,因为您几乎不知道该函数将在何处真正退出:
void foo(int&);
int bar () {
int ret = -1;
foo (ret);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
看起来不错,看起来像SFEP,但逆向工程第三方专有libfoo显示:
void foo (int &) {
if (rand()%2) throw ":P";
}
Run Code Online (Sandbox Code Playgroud)
如果bar()是nothrow,那么这个参数不成立,因此只能调用nothrow函数.
每个可变变量都会增加代码的复杂性,并给代码维护者的大脑容量带来更大的负担.它意味着更多的代码和更多的状态来测试和验证,反过来意味着你从维护者的大脑中吸取更多的状态,反过来意味着维护者的大脑容量减少了重要的东西.
有些类没有默认构造,如果可能的话,你必须编写真正的虚假代码:
File mogrify() {
File f ("/dev/random"); // need bogus init because it requires readable stream
...
}
Run Code Online (Sandbox Code Playgroud)
要宣布它,这是一个非常黑客.