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

删除拷贝构造函数后C++变量为何能通过函数返回值初始化?

删除拷贝/移动构造后返回值仍能初始化对象的原因分析

问题代码

class CameraBuffer;
class CameraBufferAccessor{
  friend CameraBuffer;
  private:
    CameraBufferAccessor(const int &data, const int &mutex);
  public:
    CameraBufferAccessor() = default;
    CameraBufferAccessor(const CameraBufferAccessor &) = delete;
    CameraBufferAccessor(CameraBufferAccessor &&) = delete;
    void operator=(const CameraBufferAccessor &other) = delete;
    void operator=(CameraBufferAccessor &&other) = delete;
};
class CameraBuffer {
  public:
    const CameraBufferAccessor getReadAccess() const {
        return {1, 2};
    }
};
int main() {
    auto buffer = CameraBuffer();
    CameraBufferAccessor a = buffer.getReadAccess();
    CameraBufferAccessor b = a;
}

问题解析

CameraBufferAccessor b = a;因拷贝构造被显式删除报错符合预期,但CameraBufferAccessor a = buffer.getReadAccess();能正常编译,核心原因是编译器触发了返回值优化(RVO),且这种优化不受拷贝/移动构造函数删除的限制:

  1. RVO的核心逻辑:当函数返回临时对象,且该对象直接用来初始化另一个同类型对象时,编译器会跳过中间的拷贝/移动步骤,直接在目标对象(main中的a)的内存地址上构造返回值。不管你用return {1,2}还是return CameraBufferAccessor(1,2),只要符合条件,都会触发这个优化。
  2. 标准的特殊许可:C++标准明确规定,即使拷贝/移动构造函数被删除或不可访问,只要编译器可以执行RVO,代码依然合法。因为优化后的流程完全不需要调用拷贝/移动构造——对象直接在最终位置被构造。
  3. RVO触发的常见场景:
    • 返回未命名临时对象(如return CameraBufferAccessor(1,2)或列表初始化的临时对象)
    • 返回与返回类型完全匹配的局部变量(如函数内定义CameraBufferAccessor temp(1,2); return temp;)
      主流编译器(GCC、Clang、MSVC)默认开启RVO,若要禁用可使用编译选项-fno-elide-constructors,此时CameraBufferAccessor a = buffer.getReadAccess();会因无法调用拷贝/移动构造而报错。

内容的提问来源于stack exchange,提问作者SᴀQɪB M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:40:15