在C++中省略return语句

23

我刚刚遇到了一些奇怪的行为,来自我使用Strawberry Perl获取的Windows版本g++编译器。它允许我省略返回语句。

我有一个成员函数,返回一个由两个指针组成的结构体,名为boundTag

struct boundTag Box::getBound(int side) {
    struct boundTag retBoundTag;
    retBoundTag.box = this;
    switch (side)
    {
        // set retBoundTag.bound based on value of "side"
    }
}

这个函数给我了一些错误的输出,后来我发现它没有返回语句。我本意是要返回retBoundTag,但是忘记写了返回语句。当我添加了return retBoundTag;后一切都正常了。

但是在添加返回语句之前,我已经对这个函数进行了测试,并且得到了正确的boundTag输出。即使现在,当我删除返回语句时,g++也没有警告地编译通过了。WTF?它会猜测返回retBoundTag吗?


6
你应该使用"-Wall"来进行编译。缺少返回语句会被"-Wreturn-type"捕获到。 - jweyrich
我倾向于使用-Werror=return-type将有关缺少返回值的警告转换为错误。这样做为我节省了很多时间。 - Krzysztof Voss
3个回答

22
在一个非void函数中省略了return语句(除了main()函数),并在代码中使用了返回的值,会导致未定义的行为

ISO C++-98[Section 6.6.3/2]

只有在返回值的函数中才能使用带表达式的返回语句;该表达式的值将返回给调用该函数的程序。如果需要,表达式将被隐式转换为其所出现的函数的返回类型。返回语句可以涉及临时对象(class.temporary)的构造和复制。从函数末尾流出相当于没有返回值的返回语句。这会导致具有返回值的函数产生未定义行为

例如:

int func()
{
    int a=10;
    //do something with 'a'
    //oops no return statement
}


int main()
{
     int p=func();
     //using p is dangerous now
     //return statement is optional here 
}

通常情况下,g++会给出一个warning: control reaches end of non-void function的警告。尝试使用-Wall选项进行编译。


7
不写返回语句是可以的。如果函数执行到结尾没有遇到返回语句,则会导致未定义的行为。你可以在到达函数结尾前返回,或通过抛出异常退出,或者根本不离开函数,所有这些都将被定义良好。 - Dennis Zickefoose
为什么使用 p 是危险的? - ajay
2
@ajay:这是因为它没有包含任何指定的值。 - Prasoon Saurav
1
实际上,使用-Wall甚至-Werror编译并没有显示这个错误。至少在Ubuntu上使用g++ 4.8.1时是这样的。不过,-Wreturn-type确实有所帮助。 - yvan vander sanden
3
根据标准,您可以安全地在main()函数中省略返回语句,函数的返回值默认为0。 - Xupicor
显示剩余3条评论

16

C和C++不需要你有一个return语句。也许没有必要有一个,因为函数进入了一个无限循环或者抛出了异常。

Prasoon已经引用了标准的相关部分:

[第6.6.3/2节]

只有在返回值的函数中才能使用具有表达式的return语句;表达式的值将被返回到函数的调用者。如有必要,该表达式将隐式转换为它所出现的函数的返回类型。返回语句可能涉及到临时对象(class.temporary)的构造和复制。从函数流出相当于返回一个没有值的结果;这在返回值的函数中会导致未定义行为。

这意味着没有返回语句是可以的。但是到达函数结尾而没有返回是未定义行为

编译器不能总是检测到这些情况,因此它不一定是一个编译错误(它必须解决停机问题才能确定是否实际上到达了函数的结尾)。如果发生这种情况,只是未定义的结果。它可能看起来可以工作(因为调用函数只会查看应该返回值所在位置的任意值),它可能会崩溃,或让恶魔从你的鼻子里飞出来。


3
谢谢您解释为什么在非void函数中不需要明确的返回声明,这不是一个编译错误 :) - ajay

3
尽管C++编译器不能总是检测到函数不能执行返回语句的情况,但它通常可以。
好消息是,至少g++通过命令行编译器选项“-Wreturn-type”使这变得容易检测。您只需要记得启用它即可。(如果使用“-Wall”,它也会被启用。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接