C++中复制消除(copy elision)与NRVO能否在递归函数中生效?
具名返回值优化(NRVO)在递归函数中是否生效?
在C++中,编译器允许执行复制消除(copy elision),其中的**具名返回值优化(NRVO)**可以让函数的局部变量无需通过move()转移到调用者栈帧,而是直接在调用者的栈帧中构造。那这种优化能不能在递归函数里生效?还是说应该让调用者手动传入存储空间?
假设NRVO生效的递归实现
vector<MyClass*> MyClass::GetHeirarchy() { vector<MyClass*> apclass; if (pclassParent) apclass = pclassParent->GetHeirarchy(); apclass.push_back(this); return apclass; }
不依赖NRVO的实现
void MyClass::GetHeirarchy(vector<MyClass*>* papclass) { if (pclassParent) pclassParent->GetHeirarchy(papclass); papclass->push_back(this); }
核心结论
NRVO在这个递归场景里无法生效
NRVO的生效条件是函数内的返回变量从构造到返回全程没有被赋值覆盖,但你写的递归代码里,每一层的apclass都会先接收上层递归返回的vector(要么移动赋值,要么拷贝赋值),再追加元素。这个赋值操作是无法消除的,编译器没法把所有递归层的apclass合并到最外层调用者的栈帧中,自然触发不了NRVO。手动传入存储空间的实现更可靠高效
第二种写法全程复用同一个vector,所有递归层直接往同一个容器里追加元素,没有任何额外的容器创建、移动或拷贝操作,性能稳定且不依赖编译器的优化行为——毕竟NRVO是编译器“可选”的优化,不同编译器或编译选项下可能失效,导致代码性能波动。
另外,第一种写法虽然符合“函数返回结果”的直觉,但实际运行时每一层递归都会生成临时vector,哪怕是移动赋值也存在指针拷贝的开销,相比之下第二种实现的效率更高。
内容的提问来源于stack exchange,提问作者Swiss Frank
相关产品推荐
相关产品推荐

