代码之家  ›  专栏  ›  技术社区  ›  Alex B

如何在没有结束返回语句的情况下编译C++代码?

  •  2
  • Alex B  · 技术社区  · 15 年前

    我遇到了以下编译良好的代码(使用Visual Studio 2005):

    SomeObject SomeClass::getSomeThing()
    {
        for each (SomeObject something in someMemberCollection)
        {
            if ( something.data == 0 )
            {
                return something;
            }
        }
        // No return statement here
    }
    

    如果方法的末尾没有返回语句,为什么要编译该语句?

    4 回复  |  直到 15 年前
        1
  •  20
  •   JaredPar    15 年前

    这是为了支持与C的向后兼容性,C并不严格要求从所有函数返回。在这些情况下,返回位置(堆栈或寄存器)只剩下最后一个值。

    如果这是在没有警告的情况下编译的,尽管您可能没有将错误级别设置得足够高。大多数编译器现在都会对此发出警告。

        2
  •  5
  •   yesraaj    15 年前

    将警告级别设置为4并尝试。并非所有控制路径都返回一个值,即我记得收到此警告的警告。

        3
  •  5
  •   Adam Rosenfield    15 年前

    可以编写保证始终返回值的代码,但编译器可能无法理解这一点。一个简单的例子是:

    int func(int x)
    {
        if(x > 0)
            return 1;
        else if(x == 0)
            return 0;
        else if(x < 0)
            return -1;
    }
    

    就编译器而言,可能所有3个 if 语句计算为 false ,在这种情况下,控件将从函数的末尾脱落,返回未定义的结果。然而,从数学上讲,我们知道这是不可能发生的,所以这个函数定义了行为。

    是的,一个更聪明的编译器可能能够解决这个问题,但是想象一下,在整数比较中,我们调用了在单独的翻译单元中定义的外部函数。然后,作为人类,我们可以证明所有的控制路径都返回值,但是编译器肯定无法理解这一点。

    允许这样做的原因是为了与C兼容,而C允许这样做的原因是为了与C标准化(pre-ansi)之前编写的遗留C代码兼容。有一些代码确实做到了这一点,所以为了让这些代码保持有效和无错误,C标准允许这样做。尽管如此,让控件从函数中脱离而不返回值仍然是未定义的行为。

    任何一个合适的编译器都应该对此提供警告;根据您的编译器,您可能必须将警告级别提高一点。我认为GCC的警告选项是 -Wextra 其中还包括一系列其他警告。

        4
  •  0
  •   mcjabberz    15 年前

    可能您的特定编译器没有像它应该做的那样做良好的流控制分析。

    您使用的编译器版本是什么?您使用什么开关进行编译?