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

删除拷贝构造函数后,是否需额外删除拷贝/移动赋值运算符及移动构造?

你的类禁止拷贝/移动的代码优化与规则解析

嘿,咱们一步步来理清楚这个问题,结合C++标准里的特殊成员函数生成规则,就能明白哪些代码是必要的,哪些是多余的:

1. 移动构造函数:完全没必要额外删除

当你显式声明(包括用= delete禁用)了拷贝构造函数的时候,编译器就不会再自动生成默认的移动构造函数了。你已经写了Foo(const Foo&) = delete;,这就属于显式声明拷贝构造,所以编译器根本不会给Foo类生成默认的移动构造,完全不用多写Foo(Foo&&) = delete;这一行。

2. 拷贝赋值运算符:必须显式删除

这里要注意:禁用拷贝构造,并不会阻止编译器生成默认的拷贝赋值运算符。如果你不手动删掉operator=(const Foo&),编译器会自动生成一个默认版本,那你的类还是能通过赋值操作被拷贝,这就违背了你“不想被拷贝/移动”的初衷。所以这一行是必须保留的。

3. 移动赋值运算符:同样不需要额外删除

和移动构造的规则一样,只要你显式声明了拷贝构造函数(哪怕是禁用它),编译器就不会自动生成默认的移动赋值运算符。所以你写的Foo& operator=(Foo&&) = delete;也是多余的,删掉完全不影响效果。

额外小提示:你的代码里有一行冗余的禁用

你写的Foo(Foo&) = delete;其实是没必要的——C++编译器默认生成的拷贝构造函数是带const Foo&参数的版本,非const引用的拷贝构造函数本来就不会被自动生成,除非你自己之前显式声明过它。所以这一行可以直接删掉,不影响禁止拷贝的效果。

最终简化后的最优代码

如果你的目标是让类完全不可拷贝、不可移动,只需要这么写就足够了:

class Foo { 
public: 
    Foo(const Foo&) = delete; 
    Foo& operator=(const Foo&) = delete; 
};

这么写的效果是:

  • 直接禁用了拷贝构造,没法通过构造的方式拷贝对象
  • 禁用了拷贝赋值,没法通过赋值的方式拷贝对象
  • 因为显式声明了拷贝构造,编译器不会生成默认的移动构造和移动赋值,自然也就彻底阻止了移动操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:02:33