当您调用函数时,如果传递给函数的参数不是数组,或者不是有意使用与号 (&
) 符号按引用传递,则这些参数将按值传递。例如,
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;
}
整数文字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() {}
整数文字不得存储在任何地方。它们甚至不需要出现在可执行二进制文件中。对于代码中的其他代码示例也是如此。欲了解更多详情,请参阅What exactly is the "as-if" rule?和 Storage of literal constants in 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
文字5
没有存储在任何地方。如果您愿意,可以尝试将 int x = 5;
传递给 lambda,这不会产生任何影响。正如 PaulMcKenzie 在评论中提到的,您可以将带有循环的 lambda 转换为递归函数,您仍然会看到相同的效果:任何地方都没有 5
。
Gcc 正确地认识到上述代码的可观察行为是(用简单的英语术语):“从 main 返回 10”,因此它产生了执行此操作的输出。现在你问“5
存储在哪里?”但该代码只是描述从 main
返回 10
的复杂方式,并且不需要在任何地方存储 5
。
关于c++ - 函数调用中的堆栈分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75736567/