You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++按值返回函数return语句初始化规则及std::move对NRVO的影响

C++ return语句std::move相关问题解答

疑问1:通用场景下的初始化规则

你提到的两处初始化属于完全独立的两个阶段,不存在冲突:

  • cppreference描述的*copy initialization(复制初始化)*作用的对象是函数的返回值对象,属于函数执行return语句时的内部逻辑:执行return local;时,会用local作为初始化源,复制初始化该函数的返回值对象。
  • 你提到的A a1(nrvo());属于调用方的初始化逻辑:nrvo()的返回值是prvalue,C++17起强制要求prvalue初始化目标对象时直接构造在目标地址,不需要生成临时对象,因此这里是直接初始化a1。

NRVO属于可选的拷贝消除优化,当return的是符合条件的局部变量名时,编译器会直接把局部变量local构造在返回值的内存地址上,省略复制/移动构造步骤。结合C++17的强制prvalue消除,local会直接构造在a1的内存地址上,因此你只会看到一次Constructed输出。

疑问2:std::move场景下的规则验证

你的理解大部分正确,补充修正几点规则:

  1. std::move(local)返回的是A&&类型的xvalue(属于glvalue类别),用xvalue复制初始化返回值类型A的对象时,重载决议会优先匹配移动构造函数,因此会触发A的移动构造。
  2. NRVO被禁用的核心原因是:NRVO的适用前提是return的表达式是自动存储期局部变量的名字本身,而std::move(local)是函数调用表达式,不是变量名,不符合NRVO的触发条件,编译器无法做优化,必须执行移动构造生成返回值对象。
  3. 关于初始化的冲突疑问和第一个问题逻辑一致:return阶段的复制初始化是针对函数返回值对象的,调用方的A a2(no_nrvo());是用返回的prvalue直接初始化a2,C++17强制消除了返回值到a2的额外拷贝,因此你只会看到local的构造+返回值的移动构造两次输出,符合你的运行结果。

内容的提问来源于stack exchange,提问作者Ruperrrt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 20:15:02