首页
学习
活动
专区
圈层
工具
发布
    • 综合排序
    • 最热优先
    • 最新优先
    时间不限
  • 来自专栏Andromeda的专栏

    浅谈RVO与NRVO

    RVO 和 NRVO RVO(Return Value Optimization,返回值优化)和 NRVO(Named Return Value Optimization,命名返回值优化)是编译器进行的优化技术 无优化 如果没有返回值优化(RVO)或命名返回值优化(NRVO),那么一个函数返回临时对象的一般步骤如下: 在函数内部创建临时对象。 在函数返回之前,分配内存来存储函数的返回值。 NRVO NRVO 与 RVO 类似,但适用于返回函数内部已命名的局部变量。编译器优化这个过程,允许在调用者的栈帧上直接构造局部变量,避免了将局部变量拷贝到返回值的过程。 } 在上面的例子中,NRVO 允许编译器直接在函数内部构造目标位置的 std::vector<int>对象,而不是通过拷贝构造局部变量。 在应用 NRVO 时,编译器会: 识别函数中将被返回的命名局部变量。 在调用者的栈帧上为该局部变量预留空间。 直接在该空间上构造局部变量,当函数返回时不需要移动或拷贝对象。

    55310编辑于 2024-03-13
  • 来自专栏Andromeda的专栏

    浅谈RVO与NRVO

    RVO 和 NRVO RVO(Return Value Optimization,返回值优化)和 NRVO(Named Return Value Optimization,命名返回值优化)是编译器进行的优化技术 无优化 如果没有返回值优化(RVO)或命名返回值优化(NRVO),那么一个函数返回临时对象的一般步骤如下: 在函数内部创建临时对象。 在函数返回之前,分配内存来存储函数的返回值。 NRVO NRVO 与 RVO 类似,但适用于返回函数内部已命名的局部变量。编译器优化这个过程,允许在调用者的栈帧上直接构造局部变量,避免了将局部变量拷贝到返回值的过程。 } 在上面的例子中,NRVO 允许编译器直接在函数内部构造目标位置的 std::vector<int>对象,而不是通过拷贝构造局部变量。 在应用 NRVO 时,编译器会: 识别函数中将被返回的命名局部变量。 在调用者的栈帧上为该局部变量预留空间。 直接在该空间上构造局部变量,当函数返回时不需要移动或拷贝对象。

    46910编辑于 2024-07-27
  • 来自专栏程序员的园——原创文章

    浅析RVO

    NRVO(Named Return Value Optimization,命名返回值优化)是RVO的一种特殊情况,隶属于RVO范畴。 如下的代码分别是RVO和NRVO的使用示例。 People using_rvo() { return People{10,"tommy"}; } People using_nrvo() { auto p = People{ 10,"tommy" } NRVO是在函数返回时,如果函数中的局部对象被命名为返回值,并且没有其他对象被命名为返回值,编译器可以直接在调用函数内部构造返回值对象,避免了对象拷贝操作。 返回值类型不能是引用类型 参考如下的示例代码 CPeople& using_nrvo_with_ref2() { auto p = CPeople{ 10,"tommy" }; return p "<<p_ref; return p; } 总结 RVO和NRVO的的核心思想是将局部对象直接构造在函数调用方的目标对象上,避免额外的对象拷贝。

    55410编辑于 2024-07-18
  • 来自专栏学西

    【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略

    读者须知 RVO 与 NRVO 的启用条件 虽然 RVO 和 NRVO 是编译器自动完成的优化,但是这些优化并不总是启用,具体取决于编译器的实现和配置。 NRVO 通常依赖于编译器的智能分析,虽然大多数现代编译器都能支持 NRVO,但其效果和激进程度因编译器和版本的不同而有所差异。 命名返回值优化(NRVO) 3.1 NRVO 的概念 命名返回值优化(NRVO) 是 RVO 的扩展,专门用于优化函数返回命名局部变量的情况。 由于没有启用 NRVO,因此返回值会触发两次拷贝构造和三次析构函数调用。 NRVO 则用于优化返回命名局部变量的场景,Visual Studio 2019 和 2022 的 NRVO 实现基本一致,但 2022 的编译器在复杂场景中的表现更为出色。

    79810编辑于 2024-10-09
  • 来自专栏编程小王

    【C++篇】类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略

    读者须知 RVO 与NRVO的启用条件 虽然 RVO 和 NRVO 是编译器自动完成的优化,但是这些优化并不总是启用,具体取决于编译器的实现和配置。 NRVO 通常依赖于编译器的智能分析,虽然大多数现代编译器都能支持 NRVO,但其效果和激进程度因编译器和版本的不同而有所差异。 命名返回值优化(NRVO) 3.1 NRVO 的概念 命名返回值优化(NRVO) 是 RVO 的扩展,专门用于优化函数返回命名局部变量的情况。 NRVO 针对命名局部变量的优化,能够在返回命名变量时避免临时对象和拷贝构造。 。isual Studio 2019 和 2022 的 NRVO 实现基本一致,能够在大多数情况下避免拷贝构造。 。 NRVO 则用于优化返回命名局部变量的场景,Visual Studio 2019 和 2022 的 NRVO 实现基本一致,但 2022 的编译器在复杂场景中的表现更为出色。

    58110编辑于 2024-11-20
  • 来自专栏后台公论

    C++按值返回对象那些事

    即便是C++98,编译器其实也对此有NRVO、RVO的优化,避免拷贝,只要你不去主动关闭优化,基本都能享受到。 类似的问题在StackOverflow上早有讨论。 https://stackoverflow.com/questions/4986673/c11-rvalues-and-move-semantics-confusion-return-statement NRVO 而在C++11之前有RVO(返回值优化)或NRVO(具名返回值优化),C++11以后也同样存在。都能提高C++函数返回时的效率,减少冗余的拷贝。 但是按C++11之前标准这里应该是拷贝构造,这一优化就是NRVO,当然这属于编译器厂商们自己做的优化(即使不开O1、O2这种优化,也会默认做),是非标的。 但当没有move语义时,如果去掉NRVO还是会执行拷贝的。

    1.3K10编辑于 2021-12-08
  • 来自专栏技术随笔心得

    编译器之返回值优化

    在此需要说明的是,因为自C++11起才引入了NRVO,而NRVO针对的是具名函数对象返回,而C++11之前的RVO相对NRVO来说,是一种URVO(未具名返回值优化) RVO RVO(Return Value NRVO NRVO,又名具名返回值优化(Named Return Value Optimization),为RVO的一个变种,也是一种编译器对于函数返回值优化的方式。 NRVO与RVO的区别是返回的对象是具名的,既然返回的对象是具名的,那么对象是在return语句之前就构造完成。 我们仍然以一个例子来分析编译器的NRVO都做了哪些优化。 这是因为NRVO相比于RVO,是一种要求更为严格的优化方式,编译器启用NRVO的前提条件是返回值是具名的,但并不能说一段代码可以NRVO就不能RVO。 NRVO原理 在上面内容中,我们讲述了在对一开始的代码进行了RVO优化,但是并没有彻底优化,那么,如果进行NRVO优化,编译器会将上述代码优化成什么样子呢?

    1.7K20编辑于 2022-08-25
  • 来自专栏光城(guangcity)

    现代C++之如何返回一个对象?

    2.总结 copy construct本身在RVO和NRVO两种情况下被优化了,如果再加上move反而画蛇添足。 在 C++11 之前,返回一个本地对象意味着这个对象会被拷贝,除非编译器发现可以做返回值优化(named return value optimization,或 NRVO),能把对象直接构造到调用者的栈上

    1.7K20发布于 2019-12-30
  • C++类与对象(4)

    同样,我们对比一下优化前后 说明:图中的 NRVO 是 命名返回值优化 (C++标准并未说明NRVO可优化,只是编译器的优化) 左图是未优化的时候,f2内构造了一个A类,然后拷贝构造了临时对象,A类销毁 前面是说的是NRVO 现在 讲一下URVO (U就是unname,未命名的,匿名返回值优化) 他原理和NRVO类似,展示代码: f2内函数简化为直接返回匿名对象,这个效果和上面的NRVO一样,右下图为未优化的场景

    17410编辑于 2025-12-20
  • 来自专栏程序员

    深入C++对象生命周期:从构造到析构的奥秘

    三、编译器的魔法:返回值优化(RVO/NRVO)考虑一个“昂贵”的类和一个创建它的函数:收起代码语言:C++运行AI代码解释ExpensiveObjectcreateExpensive(){ExpensiveObjectobj RVO/NRVO允许编译器直接在函数调用者(main函数中eo对象)的内存位置上构造本应在函数内部返回的对象。 NRVO:适用于返回有名字的局部对象(如上面的returnobj;)。汇编视角:查看开启优化(-O2)前后的汇编代码,你会看到天壤之别。 编译器的RVO/NRVO优化默默消除了价值昂贵的拷贝,让你可以更直观地编写代码而不牺牲性能。在生命终结时,析构函数必须小心翼翼地处理资源,并遵守“绝不抛出异常”的铁律,与异常机制安全共舞。

    25600编辑于 2025-09-16
  • 来自专栏C / C++

    C++引用专题(下):传值返回 VS 传引用返回

    返回局部变量的拷贝(安全) std::string getString() { std::string local = "Hello"; return local; // 返回拷贝(可能触发NRVO BigData b2 = b1.moveFrom(); // 移动构造 } 三、最佳实践指南 1、优先传值返回: 返回局部变量或临时对象时 当需要独立副本时 现代C++的返回值优化(RVO/NRVO getConfigValue() const { static std::string value = loadConfig(); return value; } 5、返回值优化(RVO/NRVO

    20910编辑于 2025-11-13
  • 来自专栏腾讯技术工程官方号的专栏

    每个C++工程师都要了解的十个性能陷阱

    NRVO(返回值优化)不友好,见下文 NRVO 的部分。 (八)返回值优化 NRVO(Named Return Value Optimization) 当一个函数的返回值是当前函数内的一个局部变量,且该局部变量的类型和返回值一致时,编译器会将该变量直接在函数的返回值接收处构造 std::cout << "&arg = " << &arg << '\n'; } int main() {   Noisy v = f();   g(f()); } 这段代码中,函数 f()满足 <em>NRVO</em> 而在某些情况下,move 反而会导致负优化,比如阻碍了 <em>NRVO</em>: Noisy f() {   Noisy v = Noisy();   return std::move(v); } 还是上面的代码,只不过返回值被改成 destructed at 0x7ffc54006d0f destructed at 0x7ffc54006d0e 工厂返回 std::optional 同样的,使用 std::optional 也可能会阻碍 <em>NRVO</em>

    2.2K41编辑于 2022-11-03
  • 来自专栏C / C++

    C++引用专题(上):详解C++传值返回和传引用返回

    返回拷贝(可能被RVO优化) } 3、底层工作原理 函数内部创建要返回的对象 将该对象拷贝到调用方的接收位置(可能被编译器优化) 函数栈帧销毁,局部变量被清理 4、编译器优化(RVO/NRVO Optimization): 编译器消除临时对象的构造和拷贝 std::string func() { return std::string("hello"); // 可能直接在调用方内存构造 } NRVO 、C++实践 1、默认优先使用传值返回: // 现代C++编译器能很好优化 std::vector<int> getData() { return {1, 2, 3}; // 依赖RVO/NRVO

    29610编辑于 2025-11-13
  • 来自专栏【腾讯云开发者】

    10大性能陷阱!每个C++工程师都要知道

    NRVO(返回值优化)不友好,见下文NRVO的部分。 (八)返回值优化NRVO(Named Return Value Optimization) 当一个函数的返回值是当前函数内的一个局部变量,且该局部变量的类型和返回值一致时,编译器会将该变量直接在函数的返回值接收处构造 { std::cout << "&arg = " << &arg << '\n'; } int main() { Noisy v = f(); g(f()); } 这段代码中,函数f()满足<em>NRVO</em> 而在某些情况下,move反而会导致负优化,比如阻碍了<em>NRVO</em>: Noisy f() { Noisy v = Noisy(); return std::move(v); } 还是上面的代码,只不过返回值被改成 destructed at 0x7ffc54006d0f destructed at 0x7ffc54006d0e 工厂返回std::optional 同样的,使用std::optional也可能会阻碍<em>NRVO</em>

    1.6K30编辑于 2022-11-03
  • 来自专栏韩曙亮的移动开发专栏

    【C++ 语言】面向对象 ( 函数重载 | 运算符重载 | 运算符重载两种定义方式 | 拷贝构造方法 | RVO 优化 | NRVO 优化 )

    文章目录 函数重载 运算符重载 ( 类内部定义云算符重载 ) 运算符重载 ( 类外部定义运算符重载 ) 可重载的运算符 拷贝构造方法 编译器优化 ( RVO 优化 | NRVO 优化 ) 完整代码示例 Xcode 的 C++ 编译器是 GNU g++ rvo 优化 , 在 VS 中, cl 编译器在 debug 模式下,会执行 rvo (return value) 优化 , 减少了1次拷贝和析构的操作 ; nrvo 优化 , 在 release 模式下 , 会执行 nrvo 优化 , 会进行 0 次拷贝 , 减少了 2 次拷贝和析构的操作 , 其优化方式是改写方法 , 直接将接收对象放入参数 , 在方法中就将返回对象赋值给接收对象了 { this->number = o.number; cout << "Operator 对象执行拷贝操作" << endl; } //这里针对拷贝操作进行说明 : rvo 优化 , nrvo 中, cl 编译器在 debug 模式下,会执行 rvo (return value) 优化 // rvo 优化 , 减少了1次拷贝和析构的操作 //在 release 模式下 , 会执行 nrvo

    78820编辑于 2023-03-27
  • 来自专栏学习成长指南

    C++--对象作为返回值-----拷贝构造函数不执行的问题解决方案

    )我们按照下面的步骤打开属性,看一下序号5的优化是否已经禁止使用,如果不是进行设置,使其禁止使用; (2)如果还是解决不了问题,在优化下面找到命令行的设置,在命令行的其他选项:加上途中的代码:/Zc:nrvo

    64110编辑于 2025-02-24
  • 来自专栏the big bang of theory

    C++右值引用小说明

    不过最近在函数返回临时对象的case下发现一些不同: 有一条原则是在NRVO时候,如果函数体内存在不同的分支返回不同的变量 如if x return a; else return b; 则RVO失效,试验了下有下面的结果

    1.5K30发布于 2019-03-28
  • 来自专栏【腾讯云开发者】

    一文入魂:妈妈再也不用担心我不懂C++移动语义了!

    name = nullptr; } } private: int val; char* name;}; (三)避免非必要的std::move调用 在C++中,存在称为“NRVO 在没有NRVO的情况下,当执行语句MyClass myClass=GetTemporary();时,会调用MyClass类的拷贝构造函数,通过对象A来拷贝创建myClass对象。 因此,编译器会启用NRVO,直接让myClass对象使用对象A。这样一来,在整个过程中,我们只有一次创建对象A时构造函数的调用开销,省去了拷贝构造函数以及析构函数的调用开销: 为NRVO点赞! 同时,遗憾的是,由于std::move(A)返回的类型是MyClass&&,与函数的返回类型MyClass不一致,因此编译器也不会使用NRVO。 因此,当返回局部对象时,我们不用画蛇添足,直接返回对象即可,编译器会优先使用最佳的NRVO,在没有NRVO的情况下,会尝试执行移动构造函数,最后才是开销最大的拷贝构造函数。

    1.7K20编辑于 2022-01-25
  • 来自专栏技术随笔心得

    性能大杀器:c++中的copy elision

    Default ctor Default ctor 通过这个输出,可以看出,编译器忽略了拷贝构造函数的调用,而是直接构造o1和o2对象,这种方式在性能上有了很大的提升,编译器对o1和o2的这种优化方式称为RVO和NRVO 现在,我们仔细回想下前面的示例代码,在编译的时候,都加上了-std=c++11这个选项,这是因为笔者的gcc11.4默认情况下是用的c++17,而c++17是能够保证RVO优化的,单独对NRVO则不能保证

    56610编辑于 2024-04-23
  • C++ 进阶特性深度解析:从友元、内部类到编译器优化与常性应用

    编译器优化的时候,会先通过语法分析发现aa最终构造在aa1上,就会直接把中间的临时对象省略,一把拿下 这个优化的名字就叫NRVO,其是在C++17中的标准提出的。 N就是name,返回一个有名字的对象,R就是return 相关文档 URVO就是返回一个匿名对象,C++17是规定了URVO的优化,NRVO还没有规定,但是代码中的NRVO是有优化的,所以编译器是超前的

    14210编辑于 2025-12-30
领券