C++ NRVO

发布时间:2026/6/25 14:34:57
C++ NRVO NRVONamed Return Value Optimization具名返回值优化是 C 中一种编译器优化技术旨在消除函数返回对象时产生的临时对象和多余的拷贝操作。它是 RVOReturn Value Optimization返回值优化的一种特例专门处理返回具名变量即有名字的局部变量的场景。为什么需要 NRVO先看一个没有 NRVO 时的场景class MyClass { public: MyClass() { std::cout Constructor\n; } MyClass(const MyClass) { std::cout Copy Constructor\n; } ~MyClass() { std::cout Destructor\n; } }; MyClass createObject() { MyClass obj; // 具名局部变量 return obj; // 理论上创建临时对象 两次析构 } int main() { MyClass a createObject(); }没有 NRVO 时的理想化步骤假设编译器不做任何优化createObject()内部构造obj调用构造函数return obj时用obj拷贝构造一个临时对象调用拷贝构造函数createObject()结束时obj析构调用析构函数用临时对象拷贝构造a调用拷贝构造函数临时对象析构调用析构函数输出可能类似Constructor // obj 构造 Copy Constructor // obj → 临时对象 Destructor // obj 析构 Copy Constructor // 临时对象 → a Destructor // 临时对象析构NRVO 如何工作启用 NRVO 后编译器会直接在函数外部预先分配的空间上构造对象跳过中间所有拷贝步骤。NRVO 优化后的步骤编译器在函数调用前就在main的栈帧上为a预留空间将这个空间的地址偷偷传给createObject()createObject()直接在传入的地址上构造obj此时obj和a其实是同一个地址直接把obj当作返回值使用无需拷贝函数结束时也无需析构obj因为它就是a本身输出变为Constructor // 直接在 a 的地址上构造关键机制编译器会把函数签名从MyClass createObject()在底层改写成类似void createObject(MyClass* this_ptr)的形式让函数直接在目标位置构造对象。代码示例对比// 示例 1NRVO 生效 MyClass createObject() { MyClass obj; // 具名变量 return obj; // NRVO直接优化掉拷贝 } // 示例 2RVO 生效匿名临时对象 MyClass createObject() { return MyClass(); // RVO构造临时对象直接作为返回值 } // 示例 3NRVO 失效的情况 MyClass createObject(bool condition) { MyClass obj1; MyClass obj2; return condition ? obj1 : obj2; // 编译器无法确定返回哪个NRVO 失效 }