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

禁用拷贝语义后,继承场景下std::vector的emplace_back为何失效?

问题原因分析

核心问题在于C++中特殊成员函数的自动生成规则,以及std::vector对移动语义的要求:

1. 显式声明析构函数会抑制默认移动构造的生成

当你在MyClass中显式定义了析构函数~MyClass() override {}时,C++编译器会停止自动生成默认的移动构造函数和移动赋值运算符。

  • 虽然基类NonCopyable有默认的移动构造,但派生类不会自动继承或生成对应的移动构造。此时MyClass实际上没有可用的移动构造函数。

2. std::vector的扩容依赖可用的移动/拷贝语义

std::vector在需要扩容时(比如emplace_back导致容量不足),需要将现有元素转移到新内存中:

  • 优先使用noexcept的移动构造函数;
  • 如果没有可用的移动构造,会尝试使用拷贝构造函数——但MyClass继承了NonCopyable的拷贝构造删除,因此编译报错。

3. MyClass2正常的原因

MyClass2显式声明了MyClass2(MyClass2 &&) noexcept = default;,即使有自定义析构函数,编译器仍会生成符合要求的移动构造函数,满足std::vector对移动语义的需求,因此编译正常。

4. 注释析构函数后正常的原因

当你注释掉MyClass的析构函数时,MyClass没有显式声明任何特殊成员函数(析构、拷贝、移动),编译器会自动生成默认的移动构造函数:

  • 这个默认移动构造会调用基类的移动构造,且默认是noexcept的,完全符合std::vector的要求。

修复方案

给MyClass显式添加默认的移动构造和移动赋值即可:

class MyClass : public NonCopyable
{
public:
    MyClass() = default;
    ~MyClass() override {}
    
    // 显式声明默认移动构造和赋值
    MyClass(MyClass &&) noexcept = default;
    MyClass &operator=(MyClass &&) noexcept = default;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:22:10