提问人:ConventionalProgrammer 提问时间:3/15/2023 最后编辑:Benjamin BuchConventionalProgrammer 更新时间:3/15/2023 访问量:126
函数调用中的堆栈分配
Stack allocation in a function call
问:
调用函数时,如果传递给函数的参数不是数组,或者不是故意使用与号()符号通过引用传递的参数,则将按值传递。例如&
void boo (int a, int b) {}
int main() {
int var1 {1};
int var2 {2};
boo(var1,var2);
return 0;
}
在此方案中,整数变量的值被复制到函数参数中,并存储在为函数分配的堆栈帧中。我的问题是:var1
var2
a
b
boo()
如果我写
void boo (int a, int b) {}
int main() {
boo(1,2);
return 0;
}
整数文本是否不存储在堆栈帧中,因为它们现在是 r 值?1
2
main()
如果我改写
void boo (int &a, int &b) {}
int main() {
int var1{1};
int var2{2};
boo(var1,var2);
return 0;
}
是参数,并且仍然存储在函数的堆栈帧中作为某种备份等。还是它们只是对实际参数的引用?a
b
boo()
var1
var2
答:
您编写的代码不是针对 cpu 的指令。它是编译器的说明。读完这个答案后,你可能会争辩说你的代码只是一个简化的例子,但和你的编译器一样,我只能使用你提供的东西。编译器将代码转换为计算机指令,这些指令具有 c++ 标准中为代码指定的可观察行为。
您的代码:
void boo (int a, int b) {
}
int main() {
int var1 {1};
int var2 {2};
boo(var1,var2);
return 0;
}
具有与此完全相同的可观察行为:
int main() {}
整数文本不得存储在任何地方。它们甚至不需要出现在可执行二进制文件中。代码中的其他代码示例也是如此。有关更多详细信息,我建议您参考“假设”规则到底是什么? 以及 c++ 中文字常量的存储。
为了说明起见,请考虑一个不同的示例:
int main() {
return [](int x){
int sum = 0;
for (int i=0;i<x;++i) sum += i;
return sum;
}(5);
}
与其在语言律师的基础上讨论它,我希望它足以证明启用优化的 gcc 会产生以下输出:
main:
mov eax, 10
ret
文本不存储在任何地方。如果您愿意,您可以尝试传递给 lambda,这不会有什么不同。正如 PaulMcKenzie 在评论中提到的,您可以将带有循环的 lambda 转换为递归函数,您仍然会看到相同的效果:No anywhere。5
int x = 5;
5
Gcc 正确地意识到上述代码的可观察行为是(用简单的英语术语来说):“return 10 from main”,因此它产生了这样做的输出。现在你问“存储在哪里?但代码只是描述返回的一种复杂方式,不需要存储在任何地方。5
10
main
5
评论
/* some code */
return foo(5);
foo(5)
评论