被调用的函数究竟什么时候结束
When exactly does a called function end?
在我读的一本教科书中,据说对于具有返回值的函数,返回值用于初始化调用站点上的临时函数。
我想知道的是,在被调用函数退出之前还是之后会发生这种情况?换句话说,如果我在被调用的函数中定义了一个变量(比如int
),它会在临时初始化之前或之后被销毁吗?
这是技术视图。这对语言律师来说可能并不有趣,但对其他人来说,这可能对我很有启发性。
函数以将控制权转移回调用方的分支指令精确结束。在此之前,被调用者拥有完全控制权,在此之后,调用者拥有对CPU操作的完全控制权。通常,只有一条CPU指令用于此控制传输。在X86-64上,这是ret
指令,PowerPC使用blr
,其他CPU也有相同的名称。不过,名字并不重要。
函数本身职责范围内的任何事情都必须在该指令之前发生,任何与被调用者无关的事情都必须发生在其他地方。
由于调用方不知道函数创建了哪些变量,因此调用方不能负责销毁这些变量。更一般地说,被调用者必须释放它为自己的目的分配的任何堆栈空间。因此,被调用者必须在发出ret
指令退出之前自行执行此类清理。这意味着,在函数退出之前,任何局部变量都必须消失。
当涉及到从函数返回结果时,事情就有点复杂了:这需要调用方和被调用方进行协作。不同的调用约定的细节不同,但通常有两种情况:
-
返回值在寄存器中传递
在这种情况下,被调用者将返回值加载到一个已知的寄存器中,调用者将使用该寄存器访问返回值。 -
返回值在堆栈上传递。在这种情况下,被调用者将把要返回的数据放在调用者堆栈帧中的一个定义位置,并且调用者将在调用返回后检查同一内存区域中的函数结果。
TL;DR:如果某件事是函数的责任,那么它必须在函数返回(=执行ret
指令)之前发生。释放堆栈空间和将数据返回给调用者就是这样的责任。
之前
对于按值返回的函数,在函数的作用域退出之前,调用站点上的临时将初始化。否则,任何返回值都将在传递到调用站点之前被销毁。
函数在返回语句后结束
在该作用域中声明的变量将超出作用域,除非变量声明为静态,否则您将无法使用它
- 什么时候调用组成单元对象的析构函数
- 什么时候在C++中返回常量引用是个好主意
- 什么时候调用析构函数
- boost odeint什么时候真正调用观测者
- 编译器对数组声明大小的计算。什么时候发生?
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 您应该在什么时候创建自己的异常类型
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 什么时候可以使用常量装饰调用我的重载函数?
- unordered_map什么时候返回 -1?
- QCoreApplication什么时候有效?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- 什么时候用指针调用C++类构造函数
- 我不明白在这个例子中什么时候调用构造函数
- 如果真的需要std::move,我们应该什么时候声明右值refs
- P1008("prohibit aggregates with user-declared constructors")在实践中什么时候有用?
- 程序什么时候会创建多个堆
- 调用boost.asio的异步函数时,线程是什么时候创建的
- Swig/python : 什么时候需要 SWIG_init() ?
- 被调用的函数究竟什么时候结束