我刚从草莓Perl的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
输出。即使是现在,当我删除return语句时,g ++会在没有警告的情况下编译它。 WTF?它会猜测返回retBoundTag
吗?
答案 0 :(得分:16)
省略return
函数中的non-void
语句[main()
除外]并使用代码中返回的值调用Undefined Behaviour。
ISO C ++ - 98 [第6.6.3 / 2节]
可以使用带表达式的return语句 仅在返回值的函数中;表达式的值是 返回给函数的调用者。如果需要,表达式 隐式转换为函数的返回类型 出现。退货声明可能涉及构造和复制 临时对象( 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
选项进行编译。
答案 1 :(得分:12)
C和C ++不要求您拥有return
语句。
可能没有必要有一个,因为函数进入无限循环,或者因为它抛出异常。
Prasoon已经引用了该标准的相关部分:
[第6.6.3 / 2条]
带表达式的return语句只能用于返回值的函数;表达式的值返回给函数的调用者。如果需要,表达式将隐式转换为其出现的函数的返回类型。 return语句可以包含临时对象(class.temporary)的构造和复制。流出函数末尾相当于没有值的返回;这会导致值返回函数中的未定义行为。
这意味着没有一个return语句就可以了。但到达函数的末尾而不返回未定义的行为。
编译器无法始终检测到这些情况,因此不需要编译错误(它必须解决暂停问题以确定执行实际是否到达结束时功能)。它只是 undefined 如果发生这种情况会发生什么。它似乎可行(因为调用函数只会查看返回值所在位置的垃圾值),它可能会崩溃,或者让恶魔飞出你的鼻子。
答案 2 :(得分:2)
即使aC ++编译器无法总是检测到函数何时无法执行return语句,通常也可以。
从好的方面来说,至少使用g ++可以使用命令行编译器选项“-Wreturn-type”轻松检测到它。你只需要记住启用它。 (如果使用“-Wall”,它也会启用。)