C++;函数调用与堆栈上推/弹出的新块 我在C++中阅读了变量范围,遇到了一个有趣的块结构: int main(int argc, char **argv) { int local; { // New level of scope int more_local; } return 0; }
据我所知,变量是在每个块的末尾从堆栈中弹出的,该块由右大括号C++;函数调用与堆栈上推/弹出的新块 我在C++中阅读了变量范围,遇到了一个有趣的块结构: int main(int argc, char **argv) { int local; { // New level of scope int more_local; } return 0; },c++,stack,block,function-calls,C++,Stack,Block,Function Calls,据我所知,变量是在每个块的末尾从堆栈中弹出的,该块由右大括号}表示 我还了解到,函数调用也会将其变量推送到堆栈上,并在调用结束时终止,该调用由右大括号表示}: void foo() { int more_local; } int main(int argc, char **argv) { int local; foo(); return 0; } 在这两种情况下,堆栈的处理方式如何不同?两者的优缺点是什么?您可以说,您的第一个示例可以看作是一个内联函数:P
}
表示
我还了解到,函数调用也会将其变量推送到堆栈上,并在调用结束时终止,该调用由右大括号表示}
:
void foo() {
int more_local;
}
int main(int argc, char **argv) {
int local;
foo();
return 0;
}
在这两种情况下,堆栈的处理方式如何不同?两者的优缺点是什么?您可以说,您的第一个示例可以看作是一个内联函数:P
但一般来说,函数调用和打开一个新的
范围
彼此无关。调用函数时,返回地址和所有参数将被推送到堆栈上,并在函数返回后从堆栈中弹出。
当打开一个新的
范围
时,只需在该范围的末尾调用该范围内所有对象的析构函数;并不能保证这些变量所占用的实际空间会立即从堆栈中弹出。它可以,但空间也可以被函数中的其他变量重用,这取决于编译器/优化器的突发奇想。好吧,您可以说您的第一个示例可以看作是一个内联函数:P但一般来说,函数调用和打开一个新的
范围
彼此无关。调用函数时,返回地址和所有参数将被推送到堆栈上,并在函数返回后从堆栈中弹出。
当打开一个新的
范围
时,只需在该范围的末尾调用该范围内所有对象的析构函数;并不能保证这些变量所占用的实际空间会立即从堆栈中弹出。它可以,但空间也可以被函数中的其他变量重用,这取决于编译器/优化器的突发奇想。通过函数调用,您将返回地址推送到堆栈上,并创建一个新的堆栈帧。如果您只是将代码的一部分用大括号括起来,那么正如您所说的,您正在定义一个新的范围。它们就像控制语句后面的任何代码块,例如if、for、while等
你不能在这里谈论优点和缺点,因为这是两件完全不同的事情。在很多情况下,用大括号括起代码块会让您受益匪浅,这会使代码更难阅读。通过函数调用,您将返回地址推送到堆栈上,并创建一个新的堆栈框架。如果您只是将代码的一部分用大括号括起来,那么正如您所说的,您正在定义一个新的范围。它们就像控制语句后面的任何代码块,例如if、for、while等
你不能在这里谈论优点和缺点,因为这是两件完全不同的事情。在很多情况下,用大括号括起代码块会让您受益匪浅,这会使代码更难阅读。
int more\u local在这两种情况下,代码>都将放置在堆栈上。但第二个场景将有函数调用的开销
我建议你考虑一下:
void foo()
{
int local;
{ // New level of scope
int more_local_1;
}
{ // New level of scope
int more_local_2;
}
}
这里more\u local\u 1
和more\u local\u 2
可能共享相同的内存位置。曾经用过
more\u local\u 1
和more\u local\u 2
变量的第二个范围。int more\u local在这两种情况下,代码>都将放置在堆栈上。但第二个场景将有函数调用的开销
我建议你考虑一下:
void foo()
{
int local;
{ // New level of scope
int more_local_1;
}
{ // New level of scope
int more_local_2;
}
}
这里more\u local\u 1
和more\u local\u 2
可能共享相同的内存位置。曾经用过
more\u local\u 1
和more\u local\u 2
变量的第二个范围。
- 局部作用域仍然可以访问其他局部变量,而函数必须显式地传递它们需要使用的任何调用方变量
- 传递变量是一件痛苦的事情,但有时它会使代码更容易理解,以便清楚地指出作用域操作实际需要的较小的变量集(同时鼓励将操作分组到离散的功能单元中,给定适当的函数名和上下文相关的参数名,然后它们就可以重用了)
- 离线函数调用还有一些其他堆栈空间和性能开销:返回地址、保存的寄存器、调用和返回指令
- 与函数作用域相比,局部作用域在最小化包含大量内存、线程、文件描述符和/或锁等重要资源的变量作用域方面尤其有效:函数的级别越高,运行时间越长,及时清理它就越有用
- 缩短变量生存期还减少了程序员在理解和维护代码时必须在心里“跟踪”的并发变量数量:越少越好
- 有时,在执行一组类似的操作时,必须选择任意不同的标识符没有多大意义,因此一些局部作用域允许方便地“回收”标识符
- 局部作用域有点笨拙,占用了源代码中的“屏幕空间”,并且增加了缩进级别,因此在有特定的理由时使用它们,而不是在“任何时候都可以”的基础上使用它们是一个好主意
- 局部作用域仍然可以访问其他局部变量,而函数必须显式地传递它们需要使用的任何调用方变量
- 传递变量是一件痛苦的事情,但有时它会使代码更容易理解,从而清楚地指出作用域操作(以及encour)实际需要的较小的变量集