8

好吧,我用我的 C++ 编译器发现了一些奇怪的东西。

我有一段不太复杂的代码要重构,但我不小心设法离开了一条没有返回语句的路径。我的错。另一方面,当我运行它并且这条路径被命中时,它被编译并出现了段错误,显然。

这是我的问题:这是编译器错误,还是不能保证 C++ 编译器会强制在非 void 返回函数中使用 return 语句?

哦,需要明确的是,在这种情况下,这是一个没有伴随 else 的不必要的 if 语句。没有 goto,没有退出,没有中止。

4

3 回答 3

13

不能保证 C++ 编译器会强制执行此操作。C++ 函数可以通过编译器未知的机制跳出其控制流。使用 C++ 编写 OS 内核时的上下文切换就是一个例子。被调用函数(其代码不一定对调用者可用)抛出的未捕获异常是另一个异常。

其他一些语言,如 Java,明确强制在编译时使用可用的知识,所有路径都返回一个值。在 C++ 中,这是不正确的,就像该语言中的许多其他场合一样,例如访问超出其边界的数组也不会被检查。

于 2010-07-06T14:21:36.377 回答
13

我个人认为这应该是一个错误:

int f() {
}

int main() {
    int n = f();
    return 0;
}

但大多数编译器将其视为警告,您甚至可能必须使用编译器开关来获得该警告。例如,在 g++ 上,您需要 -Wall 来获得:

[neilb@GONERIL NeilB]$ g++ -Wall nr.cpp
nr.cpp: In function 'int f()':
nr.cpp:2: warning: no return statement in function returning non-void

当然,使用 g++ 你应该总是至少使用 -Wall 进行编译。

于 2010-07-06T14:24:38.767 回答
4

编译器不会强制执行此操作,因为您知道编译器实际上没有哪些路径是可能的。编译器通常只知道该特定文件,而不知道可能影响任何给定函数内部流程的其他文件。所以,这不是错误。

但是,在 Visual Studio 中,这是一个警告。我们应该注意所有警告......对吗?:)

编辑:似乎有一些关于何时发生这种情况的讨论。这是我个人代码库中经过修改但真实的示例;

enum TriBool { Yes, No, Maybe };

TriBool GetResult(int input) {
    if (TestOne(input)) {
        return Yes;
    } else if (TestTwo(input)) {
        return No;
    }
}

请耐心等待,因为这是旧代码。最初那里有一个“可能还有其他回报”。:) 如果 TestOne 和 TestTwo 位于不同的编译单元中,那么当编译器遇到此代码时,它无法判断 TestOne 和 TestTwo 是否都可以为给定的输入返回 false。作为编写 TestOne 和 TestTwo 的程序员,您知道如果 TestOne 失败,那么 TestTwo 就会成功。也许这些测试有副作用,所以必须做。不写“else if”会更好吗?也许。大概。但关键是这是合法的 C++,编译器不知道是否可以在没有返回语句的情况下退出。我同意,它是丑陋且不好的编码,但它是合法的,Visual Studio 会给你一个警告,但它会编译。

请记住,C++ 并不是要保护您免受自己的伤害。这是关于让你在语言的限制内做你想做的事,即使这包括在脚上开枪。

于 2010-07-06T14:21:42.020 回答