2014-09-06 126 views
2

如果我有这样的功能:功能不使用回C++

int addNumbers(int x, int y) 
{ 
    return x + y; 
} 

,如果我用它作为这样的:

cout << addNumbers(4, 5) << endl; 

它会返回并打印9。使用上面相同的cout行,如果我注释掉或删除addNumbers中的返回,它将返回并打印1。如果我这样做:

int addNumbers(int x, int y) 
{ 
    int answer = x + y; 
    //return x + y; 
} 

它将使用收益自动返回和打印9,没有我。同样,我可以写int answer = x;它将返回4。我也可以这样写:

int addNumbers(int x, int y) 
{ 
    int answer = x; 
    answer = 1; 
    //return x + y; 
} 

,它仍然会返回4.

究竟是返回,为什么?当我使用参数变量时,它只返回1以外的值,但它不返回如上例所示的变量答案,因为我将其更改为1,并且它仍然返回值x (4)

+1

这是UB,它返回,因为它发生在堆栈上,为x64构建,它将是一个“随机”值 – paulm 2014-09-06 08:43:31

+1

它是[* undefined behavior *](http://en.wikipedia.org /维基/ Undefined_behavior)。 – 2014-09-06 08:46:04

回答

2

§6.6.3[stmt.return]/P2:

流动关闭的功能的端部是相当于没有 值的return;这会导致在返回值 函数中出现未定义的行为。

main()是一个特殊的例外。流走的main()末相当于return 0;

允许UB包括:

  • 回到你“想要”返回
  • 返回垃圾值,而不是
  • 崩溃
  • 发送您的密码给黑客
  • 格式化您的硬盘驱动器
  • Mak荷兰国际集团在您的计算机爆炸和打击你的腿断
  • 咒术鼻恶魔
  • 在时间旅行回来,你的程序固定在正确的事情
  • 创建黑洞
  • ......

但严重的是,UB可以以各种方式表现出来。例如,给定这样的代码:

#include <iostream> 
bool foo = false; 
int addNumbers(int x, int y) 
{ 
    int answer = x; 
    answer = 1; 
    //return x + y; 
} 

int main(){ 
    if(!foo) { 
    addNumbers(10, 20); 
    std::cout << 1 << std::endl; 
    } 
    else { 
    std::cout << 2 << std::endl; 
    } 
} 

铛++在-02 prints2

为什么?因为它推断addNumbers(10, 20);具有未定义的行为,这允许它假定第一个分支从未被采用并且foo始终为true,尽管这显然不是这种情况。

+0

因此,即使在这一个(非常基本的)场景中,它总是会返回我“预计”它返回的结果,但在其他机器或更复杂的场景中肯定无法保证? – Sam 2014-09-06 08:54:00

+0

@Sam它不保证任何事情。 * UB可能会发生任何事情。 – 2014-09-06 08:56:27

+0

感谢您的回答,您添加的示例真的有所帮助。奇怪的东西,真的很有趣。 – Sam 2014-09-06 09:21:31

0

您正在观察未定义的行为。 “为什么”该程序没有很好的理由,因为它不是一个格式良好的程序。它可以做任何事情,包括运行时从磁盘删除自己。启用编译器警告和错误(例如g++ -Wall -Wextra -Werror),您将被自动禁止编写此类代码(如您应该那样)。

1

您正在依赖“未定义的行为”。对于简单类型,返回值通常存储在寄存器中,也可用于计算结果的形成。但它也可能不被使用,并且你得到一些任意的“随机”结果,并且是“未定义的行为”,你也可能得到你的计算机可能执行的任何其他可能的操作 - 例如崩溃或执行一些你没有执行的代码要执行...

0

因此,它是未定义的行为,反汇编你的二进制可能解释为什么这样的值返回。

objdump -d example.bin

由于返回值与RAX注册表关联,如果编译器使用RAX处理函数,返回的值是留在兵营的价值。

无论如何,你不应该这样做,因为当你编写这样的代码时,编译器优化和注册表的使用是未知的。