赞
踩
堆(自由存储)
栈
<1>该示例假定没有编译器优化,例如内联(用函数体替换函数调用),返回类型优化等。
此外,在函数调用时放入栈的确切顺序(调用约定)取决于平台(CPU 架构 + 操作系统 + 编译器)。
<2>程序开始。
<3>局部变量 y 被放入栈。
<4> 局部变量 i 被放入栈。
<5> 函数的返回值占位符被放入堆栈
<6> 当前指令的内存地址被放在栈上,这样在离开被调用的函数后,我们就知道从哪里恢复程序。
<7> 帧指针标记了当前函数的栈帧的开始。在当前栈帧内的一切都将被视为函数局部的。需要帧指针是因为不同的函数调用可能有不同大小的栈帧。
<8> 执行跳转到函数square的内存地址。
<9> 函数参数p放在栈上,它的值由调用参数(y的值)决定。
注意:返回地址、占位符、局部参数等放在栈上的顺序取决于平台的调用约定(CPU体系结构+ OS +编译器)。
<10> 函数局部变量 x 放到栈上。
<11> 表达式 p * p 的结果被赋给 x。
<12> 语句return x,将 x 的值复制到 返回值占位符。
<13>离开函数square时: 堆栈的顶部位置减少到堆栈帧下方;这意味着所有函数局部变量都从堆栈中弹出。
<14> 执行通过跳转到之前存储的返回地址返回到调用位置。
<15> 赋值语句int i = …会导致返回值被复制到i中。
<16> square函数的返回值被从栈中弹出。
<17> 局部变量k被放入栈。
<18> 程序结束,所有关联的变量都会从栈中弹出。
如果我们把返回类型改为int&会怎么样呢?
<1>
<2> 在从square返回之前栈内容:
现代的 C++ 编译器进行多项优化(尤其是在较高的优化级别 -O2 和 -O3),使函数调用速度更快。
Return Value Optimization 返回值优化 (RVO)
Point foo (…) {
…
return Point{…};
}
Point res = foo();
Named Return Value Optimization 命名返回值优化 (NRVO)
Point foo (…) {
Point loc;
…
return loc;
}
Point res = foo();
调用小/短函数的地方被该函数的代码替换。
内联只会发生在编译器“看到”函数声明的同时也看到它的完整定义,如果我们分别编译程序的不同部分,这种情况就不一定会发生(更多内容请参考《分离编译》章节)。
这是 C++ 性能优势的一个来源。在许多其他语言(比如 Java、C# 等)中,内联化要困难得多,有时甚至是不可能的。这些语言通常具有始终开启的多态性,这意味着所有/大多数函数/方法调用只能在运行时解析。
附上原文链接
如果文章对您有用,请随手点个赞,谢谢!^_^
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。