a(const a&) = delete; 能禁用拷贝,因为 c++11 规定显式删除的特殊成员函数在任何上下文(包括类内、友元、隐式调用)中均不可用,编译器直接报错而非不生成。

为什么 class A { A(const A&) = delete; }; 能禁用拷贝?
因为 C++11 明确规定:当用户显式将某个特殊成员函数声明为 =delete,编译器就彻底禁止对该函数的调用——哪怕是在类内部、友元里,或隐式上下文(比如传值返回)中,只要触发该函数,就会报错。这不是“不生成”,而是“生成了但立刻标记为不可用”。
常见错误现象:error: use of deleted function 'A::A(const A&)',通常出现在你把对象传值进函数、放入 std::vector、或写了 A a = b; 这类语句时。
- 它比不写拷贝构造更严格:不写可能让编译器自动生成(如果满足条件),而
=delete是铁定封死 - 必须放在 public 区域,否则连类内都无法调用(但通常你就是要对外禁用,所以 public + delete 是标准写法)
- 删除拷贝构造的同时,编译器通常也会隐式删除拷贝赋值运算符(
operator=),但保险起见建议一起显式删掉
如何同时禁用拷贝构造和拷贝赋值?
只删一个不够——很多操作(如 a = b; 或容器重分配)会尝试调用拷贝赋值;而 std::vector<a></a> 插入时可能既需要拷贝构造也需要拷贝赋值。两者得一起封。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 在类定义中,同一访问区域(通常是
public:)下并列声明:A(const A&) = delete;和A& operator=(const A&) = delete; - 不要只删构造、留着赋值:这会让
a = b;编译通过,但A c = a;报错,逻辑割裂,容易埋坑 - 如果类有移动语义,记得把移动操作也考虑进去:禁用拷贝后,若没提供移动操作,对象就完全无法转移,可能意外导致编译失败(比如
return local_a;)
示例:
class NonCopyable {
public:
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
=delete 和私有化拷贝构造有什么区别?
私有化(private: A(const A&);)是 C++98 的老办法,靠访问控制拦调用;=delete 是语义级禁止,更干净、更早报错、更明确意图。
关键差异:
- 私有拷贝构造在友元或类内部仍可调用;
=delete连友元和类内都不让调——真正“全局禁用” - 私有化时,如果误写了
A a = b;,错误信息可能是‘A::A(const A&)’ is private,而=delete给的是更直白的use of deleted function - 模板实例化中,私有化可能延迟到链接时报错;
=delete在模板实例化时就拒绝,错误位置更准
什么时候不该只删拷贝,却忘了移动?
当你禁用拷贝后,还希望对象能被安全转移(比如放进容器、作为返回值),就必须提供移动构造和移动赋值。否则,即使你写了 std::move(a),编译器也没法动——因为移动操作没定义,且编译器不会自动生成(一旦你声明了任何拷贝/移动操作,编译器就不再自动生成其余的)。
容易踩的坑:
- 只删拷贝、不写移动,结果
std::vector<a></a>的push_back(std::move(a))仍失败:因为 vector 扩容时可能需要移动元素,而移动操作不存在 - 写了
=delete但没加noexcept移动操作,可能导致某些容器(如std::vector)退化为拷贝行为(即使你禁了拷贝,它就直接编译失败) - 移动操作最好也显式定义为
=default或手动实现,并加noexcept,否则std::vector::reserve()等操作可能拒绝使用移动优化
真正想“禁拷贝但允移动”的类,典型写法是:
class MoveOnly {
public:
MoveOnly() = default;
MoveOnly(const MoveOnly&) = delete;
MoveOnly& operator=(const MoveOnly&) = delete;
MoveOnly(MoveOnly&&) noexcept = default;
MoveOnly& operator=(MoveOnly&&) noexcept = default;
};
禁用拷贝这件事本身很简单,但后续是否支持移动、是否影响容器使用、是否和友元/模板交互,这些地方才是实际项目里最容易漏掉的细节。










