我知道使用变量后的后缀运算符增量值。但在这种情况下,它是一个有效的陈述吗?因为看起来我在它的 return 语句之后修改了一个变量。
#include <iostream>
using namespace std;
int val = 0;
int foo()
{
return val++;
}
int main()
{
cout<<foo();
cout<<endl<<val;
}
任何详细说明都会有所帮助。
我知道使用变量后的后缀运算符增量值。但在这种情况下,它是一个有效的陈述吗?因为看起来我在它的 return 语句之后修改了一个变量。
#include <iostream>
using namespace std;
int val = 0;
int foo()
{
return val++;
}
int main()
{
cout<<foo();
cout<<endl<<val;
}
任何详细说明都会有所帮助。
说return val++
先返回val
然后递增它并不完全正确。该表达式val++
增加 的值val
,但计算结果为 的旧值val
。
您可以将后缀++
视为使用辅助变量来保存旧值的函数:
int temp = val; // save old value to temp
++val; // increment actual value
return temp; // evaluate to old value
是的,它是有效的。
不要认为它是返回val
然后增加它。
相反,您将返回操作的结果val++
。
好的,val
正如您可能注意到的那样,它是一个全局变量。
当你打电话时foo()
,
int foo()
{
return val++;
}
它将val
首先返回,即0
,然后增加 的值val
,因此val = 1
。
正如 Zenith 所引用的,
表达式
val++
增加 的值val
,但计算为val
增加之前的值。
现在,当您cout
val 时,val
显然是 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]
}