Gcc 4.8.3没有发现缺失'返回'关键词

时间:2014-12-14 21:54:26

标签: c++ c++11 gcc gcc4.8

让我们看一下这段代码:

#include <iostream>

int foo(int i) {return i; }

int foobar(int z) {return foo(z);}

int main() {
std::cout << foobar(3) << std::endl;
}

用g ++ -std = c ++ 11编译好...并给出输出3.但相同的输出由下式给出:

#include <iostream>

int foo(int i) {return i; }

int foobar(int z) { foo(z);}

int main() {
std::cout << foobar(3) << std::endl;
}

它没有问题编译,但很明显foobar错过了关键字返回。这是gcc 4.8.3中的错误还是我不知道某些c ++ 11原则? (在Fedora 20上运行)

2 个答案:

答案 0 :(得分:6)

C ++标准没有要求编译器在函数返回非return中坚持void - 语句。相反,在没有return语句的情况下流出这样一个函数的结尾是未定义的行为。标准中的相关陈述在6.6.3 [stmt.return]第2段,最后一句(以及在3.6.1 [basic.start.main]第5段中的陈述是main()可以流动的陈述关闭此功能):

  

离开函数末尾相当于没有值的返回;这会导致值返回函数中的未定义行为。

这种方法的主要原因是,如果函数实际上真的返回,它可能是非平凡的,甚至是不可能的。考虑这个函数声明和函数定义:

extern void will_always_throw();
int does_not_return_anything() {
    will_always_throw();
}

假设will_always_throw()确实如顾名思义所做,那就没有错。事实上,如果编译器变得更聪明并且设法验证will_always_throw(),确实总是抛出(或者“noreturn”属性附加到will_always_throw(),它可能会警告此定义中的最后一个语句永远不会到达:

int does_return_something_just_in_case() {
    will_always_throw();
    return 17;
}

处理这些情况的一般方法是编译器支持在必要时启用/禁用警告的适当选项。例如,在您的代码中,我有权访问的所有编译器(gccclangicc)会在启用警告时创建警告(前两个使用-Wall-w2用于英特尔的编译器。)

答案 1 :(得分:4)

代码编译得很好,因为它是格式良好的,所以你可以运行它。但由于这是未定义的行为,你不能依赖程序的任何行为,任何事情都是合法的。为防止此类事故,请启用编译器警告。如果您使用-Wall编译代码,则会看到

main.cpp:10:28: warning: no return statement in function returning non-void [-Wreturn-type]
 int foobar(int z) { foo(z);}

Here您可以获得有关这些警告的更多信息。使用它们并确保您的代码免费编译警告。它可以在编译时捕获代码中很多的错误。