无法内联的函数调用优化¶
(1)递归(Recursion):栈开销与缓存失效
- 问题本质:递归通过函数调用栈实现,每次调用需保存参数、局部变量、寄存器状态,栈开销大;且递归深度过深易引发栈溢出,同时破坏数据局部性,导致缓存命中率下降;
-
优化方案:
-
递归转迭代:将递归算法改写为循环,用显式栈(如数组模拟栈)存储中间状态。
// 递归版本(低效)
void preorder_recursive(Node* root) {
if (root) {
visit(root);
preorder_recursive(root->left);
preorder_recursive(root->right);
}
}
// 迭代版本(高效)
void preorder_iterative(Node* root) {
std::stack<Node*> s;
while (root || !s.empty()) {
if (root) {
visit(root);
s.push(root->right);
root = root->left;
} else {
root = s.top();
s.pop();
}
}
}
void preorder_tail_rec(Node* root) {
while (root) {
visit(root);
preorder_tail_rec(root->left);
root = root->right; // 尾递归改为循环变量更新
}
}
(2)函数参数传递:值传递vs引用传递
- 问题本质:传递大对象(如
std::vector、自定义矩阵类)时,值传递会触发对象拷贝(调用拷贝构造函数),开销远高于引用传递; -
优化方案:
-
大对象用
const&传递:对无需修改的参数,用“const 类型&”传递,避免拷贝,例如void process(const Matrix& mat); - 小类型直接值传递:对
int、float等标量类型,值传递开销与引用传递相当(甚至更快,避免指针间接访问),无需强行用引用; - 避免临时对象传递:向引用参数传递常量(如
process(5))时,编译器会自动创建临时对象,若需频繁传递常量,可重载函数适配常量参数(如void process(int val))。