24

我刚刚从 Strawberry Perl 获得的 Windows 版 g++ 中出现了一些奇怪的行为。它允许我省略返回语句。

我有一个成员函数,它返回一个由两个指针组成的结构,称为 a 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++ 也会在没有警告的情况下编译它。怎么回事?它猜想返回retBoundTag吗?

4

3 回答 3

21

省略函数 [Except ]return中的语句并在代码中使用返回值会调用Undefined Behaviornon-voidmain()

ISO C++-98[第 6.6.3/2 节]

带有表达式的 return 语句只能用于返回值的函数;表达式的值返回给函数的调用者。如果需要,表达式会隐式转换为它出现的函数的返回类型。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选项编译。

于 2010-08-04T02:33:20.120 回答
17

C 和 C++ 不要求你有一个return声明。可能没有必要有一个,因为函数进入了一个无限循环,或者因为它抛出了一个异常。

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

[第 6.6.3/2 节]

带有表达式的 return 语句只能用于返回值的函数;表达式的值返回给函数的调用者。如果需要,表达式会隐式转换为它出现的函数的返回类型。return 语句可能涉及临时对象 (class.temporary) 的构造和复制。从函数的末尾流出相当于没有值的返回;这会导致值返回函数中的未定义行为。

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

编译器不能总是检测到这些情况,所以它不需要是编译错误(它必须解决停止问题以确定执行是否真的到达函数的末尾)。如果发生这种情况应该发生什么,这只是未定义的。它可能看起来有效(因为调用函数只会查看返回值应该在的位置中的任何垃圾值),它可能会崩溃,或者让恶魔飞出你的鼻子。

于 2010-08-04T12:15:07.403 回答
3

尽管 C++ 编译器不能总是检测到函数何时不能执行 return 语句,但它通常可以。

从好的方面来说,至少 g++ 可以通过命令行编译器选项“-Wreturn-type”轻松检测到这一点。您只需要记住启用它。(如果您使用“-Wall”,它也会启用。)

于 2012-10-17T17:31:18.813 回答