-2

我知道使用变量后的后缀运算符增量值。但在这种情况下,它是一个有效的陈述吗?因为看起来我在它的 return 语句之后修改了一个变量。

#include <iostream>

using namespace std;

int val = 0;

int foo()
{
        return val++;
}

int main()
{
        cout<<foo();
        cout<<endl<<val;
}

任何详细说明都会有所帮助。

4

4 回答 4

6

return val++先返回val然后递增它并不完全正确。该表达式val++增加 的值val,但计算结果为 的旧值val

您可以将后缀++视为使用辅助变量来保存旧值的函数:

int temp = val; // save old value to temp
++val;          // increment actual value
return temp;    // evaluate to old value
于 2015-03-25T01:47:55.963 回答
2

是的,它是有效的。

不要认为它是返回val然后增加它。

相反,您将返回操作的结果val++

于 2015-03-25T01:29:47.267 回答
2

好的,val正如您可能注意到的那样,它是一个全局变量。

当你打电话时foo()

int foo()
{
    return val++;
}

它将val首先返回,即0然后增加 的值val,因此val = 1

正如 Zenith 所引用的,

表达式val++增加 的值val,但计算val增加之前的值。

现在,当您coutval 时,val显然是 1,因此输出是合理的。

于 2015-03-25T01:46:37.163 回答
1

为了查看编译器为表示您的代码所采取的确切步骤,我检查了反汇编。

第 00324C2E 行将全局变量“val”的值复制到 CPU 的 eax 寄存器中。

第 00324C33 行将值从 eax 复制到“foo”函数的本地堆栈空间。

第 00324C39 行将全局变量“val”的值复制到 CPU 的 ecx 寄存器中。

第 00324C3F 行将 ecx 寄存器中的值加 1。

第 00324C42 行将增加的值从 ecx 寄存器复制回全局变量“var”。

第 00324C48 行将值的未受影响副本复制到 CPU 的 eax 寄存器中,该副本存储在“foo”函数的本地堆栈空间(参见上面的第 00324C33 行)中。它被复制到 eax 寄存器,因为它是返回给调用函数(在本例中为“main”)的值。

因此,从 foo() 返回 0,但全局变量“val”在 foo() 返回后包含 1。


int foo()
{
  00324C10  push        ebp  
  00324C11  mov         ebp,esp  
  00324C13  sub         esp,0C4h  
  00324C19  push        ebx  
  00324C1A  push        esi  
  00324C1B  push        edi  
  00324C1C  lea         edi,[ebp-0C4h]  
  00324C22  mov         ecx,31h  
  00324C27  mov         eax,0CCCCCCCCh  
  00324C2C  rep stos    dword ptr es:[edi]  
      return val++;
  00324C2E  mov         eax,dword ptr ds:[0032F320h]  
  00324C33  mov         dword ptr [ebp-0C4h],eax  
  00324C39  mov         ecx,dword ptr ds:[32F320h]  
  00324C3F  add         ecx,1  
  00324C42  mov         dword ptr ds:[32F320h],ecx  
  00324C48  mov         eax,dword ptr [ebp-0C4h]  
}
于 2015-03-25T02:41:41.310 回答