Nav*_*een 28 c++ compiler-warnings
我试图回答这个问题.正如接受的答案所暗示的那样,该代码的问题在于并非所有控制路径都返回一个值.我在VC9编译器上尝试了这个代码,它给了我一个相同的警告.我的问题是为什么只是一个警告而不是错误?此外,如果没有返回值的路径被执行,该函数将返回什么(它必须返回一些东西)?它只是堆栈顶部的任何东西还是可怕的未定义行为?
CB *_*ley 30
无法从具有非void返回类型的函数返回值会导致未定义的行为,但不是语义错误.
据我所知,其原因主要是历史性的.
C最初没有void和隐含int意味着大多数函数返回一个,int除非显式声明返回别的东西,即使没有意图使用返回值.
这意味着很多函数返回一个int但没有显式设置返回值,但这是好的,因为调用者永远不会使用这些函数的返回值.
有些函数确实返回了一个值,但使用了隐式,int因为它int是一个合适的返回类型.
这意味着预void编码具有许多名义上返回的功能,int但可以声明返回void,许多其他功能应该返回int,没有明确的方法来区分.在任何阶段强制执行return所有非void函数的所有代码路径都会破坏遗留代码.
还有一个论点是函数中的某些代码路径可能无法访问,但这可能不容易从简单的静态分析中确定,那么为什么强制执行不必要的return?
我猜它只是一个警告,因为编译器不能总是100%确定它可能不会返回.
即如果你有:
-= source1.c =-
int func()
{
if(doSomething())
{
return 0;
}
}
-= source2.c =-
int doSomething()
{
return 1;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,编译器可能无法知道它总是会返回返回,但是你会这样做.当然,依赖于了解外部代码的工作方式,这是一种糟糕的编程习惯.
至于实际返回的内容取决于平台.在x86 ABI上,EAX用于返回值(最多32位),因此它将返回放置在该寄存器中的内容(可能是来自其他内容的返回,临时值或总垃圾).
从技术上讲,如果调用一个函数并且该函数总是抛出异常,则不能保证会出错.例如,这里有一些伪代码,你知道raiseError总是抛出.
MyClass func( params )
{
if( allIsValid() )
{
return myObject;
}
else
{
raiseError( errorInfo );
}
}
Run Code Online (Sandbox Code Playgroud)
如果编译器看不到raiseError的实现,它就不会知道该函数是否会抛出.所以实际上这里确实没有未定义的行为.当然,在这里使编译器静音是很好的,你可以在raiseError之后写一个"虚拟"返回语句,或者使用虚拟"throw".我把它们称为"虚拟",因为它们永远不会实现.(如果你真的坚持,你也可以取消警告).但是没有错误或未定义的行为.