C++ 当返回语句不存在时,为什么没有编译器错误?

C++ 当返回语句不存在时,为什么没有编译器错误?,c++,c,return-value,language-lawyer,compiler-flags,C++,C,Return Value,Language Lawyer,Compiler Flags,与Java不同,在C/C++中,允许执行以下操作: int* foo () { if(x) return p; // what if control reaches here } 这通常会导致崩溃和难以调试的问题。为什么标准不强制要求非无效函数具有最终返回?(编译器为错误的返回值生成错误) gcc/msvc中是否有任何标志强制执行此操作?(类似于-Wunused result)AFAIR Visual Studio 2008警告您“执行路径没有返回值”。这是允许的,意思是“C++不

与Java不同,在C/C++中,允许执行以下操作:

int* foo ()
{
  if(x)
    return p;
// what if control reaches here
}
这通常会导致崩溃和难以调试的问题。为什么标准不强制要求非无效函数具有最终返回?(编译器为错误的
返回值生成错误)


gcc/msvc中是否有任何标志强制执行此操作?(类似于
-Wunused result

AFAIR Visual Studio 2008警告您“执行路径没有返回值”。这是允许的,意思是“C++不会阻止你射中你的脚”。因此,您应该思考,而不是编译器。

gcc
中使用
-Wall
标志

 warning: control reaches end of non-void function

编辑:或者更具体地说是
-Wreturn类型

我的猜测:因为有时程序员比编译器知道得更好。有了这个简单的例子,很明显,有些事情是错误的,但是考虑到许多价值的转换,或者一般的许多检查。作为编码人员,您知道某些值不会传递给函数,但编译器不会,只是提示您可能有问题

#include <iostream>

int foo(){
    if(false)
        return 5;
}

int main(){
    int i = foo();
    std::cout << i;
}
#包括
int foo(){
if(false)
返回5;
}
int main(){
inti=foo();
std::cout这是不允许的(未定义的行为)。但是,在这种情况下,标准不要求诊断

标准不要求最后一条语句为
return
,因为代码如下:

while (true) {
  if (condition) return 0;
}

这总是返回0,但哑编译器看不到它。请注意,该标准并不强制要求智能编译器。在
while
块之后的
return
语句将是一种浪费,哑编译器无法对其进行优化。该标准不希望要求程序员编写浪费代码只是为了满足愚蠢的编译器


g++-Wall足够聪明,可以在我的机器上发出诊断信号。

显而易见的答案是:因为这不是一个错误。如果
x
为false,并且如果调用者使用返回值,则两者都不是 必须由编译器确定,至少在一般情况下 案例

在这种特殊情况下(返回指针),它不会太复杂 很难要求所有路径都返回
;Java就是这样做的
但是,一般来说,C++中不需要这样做,因为
C++,您可以返回用户定义的类型,因为这些类型可能不可能
构造一个值(没有默认构造函数等),这样我们就有了
程序员可能无法提供
返回的情况
在一个他或她知道不能被接受的分支中,编译器也不能
确定无法执行分支

在这种情况下,当编译器能够确定流时,大多数编译器都会发出警告。 我看到的所有这些都会在某些情况下发出警告,在这些情况下 但是,不可能从末尾掉下来。(g++和VC++都警告:

int
bar( char ch )
{
    switch ( ch & 0xC0 ) {
    case 0x00:
    case 0x40:
        return 0;

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}
,至少是通常的选择。虽然很明显
函数永远不会从末尾掉下来。)

标准对这种编程的规定是,它会产生未定义的行为

未定义的行为是C/C++的乐趣和遗憾,但它也是语言设计的一个基本特性,允许进行许多低级优化,使C成为一种“高级汇编程序”(实际上,这不是为了给您一个想法)


因此,在重定向到John关于与GCC一起使用的交换机的回答时,要知道“为什么”该标准并没有阻止这一点,我想指出对未定义行为及其所有错误的一个非常有趣的分析:。它提供了一个非常有启发性的阅读。

您可以使用以下编译器选项将警告转换为错误

-Wreturn type-Werror=返回类型


查看此

“请注意,即使MSVC上的警告级别为1,也会发出以下警告:”这很有趣。我甚至在VS 2005的第4级中也没有得到这个警告。@t.J:根据MSDN,2005在第1级也应该发出这个警告。请参阅我添加的链接。@Xeo:很有意思。如果我添加了一个类似于你的
foo
函数,我会得到错误,但如果我在自动生成的
\tmain
函数中执行完全相同的操作,则不会得到错误。主功能是特殊的(如在许多事情中)。像这样的控制流警告通常只有在Optimizer运行并进行分析时才会发出。因此它们通常仅为零售。@example:这是因为标准特别允许
main
没有返回语句。如果省略它,结果就好像最后是
return 0;
。IIRC gcc仅诊断当打开优化时,它会被忽略,因为它使用控制流分析对其进行诊断,而不进行优化时,它不会运行。@T.j.Crowder:
对于C++,没有返回类型的函数总是会生成诊断消息,即使指定了-Wno返回类型。唯一的例外是在系统头中定义的main和函数
-从
gcc-man
pageinterest中,如果我在
main
中执行,gcc不会使用
-Wall
检测到它,而是在
argc
上进行分支。但是如果我添加了一个单独的函数并在其中执行,它确实会检测到它。
main
似乎是一个特例(因为它在很多方面都是这样).Edit:@John:Overlapping comments.:-@T.J
main()
不需要包含显式的
返回值;从Bjarne Stroustrup网站上可以看到,它是由标准定义的,在下面的take-away消息中检查Shafik的答案是:如果您想要这些检查,请在gcc上使用
-Wall
,并设置高警告级别(3或4)在Visual Studio中。我一直希望有一个编译器标志,该标志将导致所有函数的末尾都有
抛出“LOL Y U HERE??”
。该行为未定义,因此任何情况都可能发生,抛出异常肯定符合任何条件。仅供验证