Gcc 4.8.3 没有发现缺少的"返回"关键字

Gcc 4.8.3 does not spot missing 'return' keyword

本文关键字:返回 关键字 发现 Gcc      更新时间:2023-10-16

让我们看一下这样的代码段:

#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 上(

C++ 标准并没有强制编译器在函数返回非void中坚持使用 return 语句。相反,在没有 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;
}

处理这些情况的一般方法是让编译器支持合适的选项,根据需要启用/禁用警告。例如,在您的代码上,我有权访问的所有编译器(gcc、clang 和 icc(都会创建一个警告,假设警告已启用(前两个使用-Wall,英特尔编译器使用 -w2(。

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

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

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