C++中引用、拷贝、移动与禁止拷贝的详细知识点总结
·
1. 引用(Reference)
- 引用是变量的别名,声明时必须初始化,之后不能再绑定到其他对象。
- 常用于函数参数和返回值,避免对象拷贝,提高效率。
- 有常量引用(const T&),可绑定到临时对象或常量,常用于只读传参。
int a = 10;
int& ref = a; // 普通引用
const int& cref = a; // 常量引用
- 内存分配:不分配新内存,仅为已有变量创建别名。
- 内存消耗:无额外消耗。
- 特性:对引用的操作直接作用于原变量,适合高效传递和修改数据。
2. 拷贝(Copy)
- 拷贝构造函数:用一个已有对象初始化新对象。
ClassName(const ClassName& other);
- 拷贝赋值运算符:将一个已有对象赋值给另一个已存在对象。
ClassName& operator=(const ClassName& other);
- 默认情况下,编译器会自动生成这两个函数,进行成员逐一拷贝(浅拷贝)。
- 对于管理资源(如指针、文件句柄等)的类,通常需要自定义拷贝操作,避免资源重复释放或泄漏(深拷贝)。
- 可以通过
= delete禁止拷贝构造和拷贝赋值,防止对象被复制,常用于资源独占类或不可复制对象。
ClassName(const ClassName&) = delete;
ClassName& operator=(const ClassName&) = delete;
- 内存分配:会分配新内存,创建原对象的副本。
- 内存消耗:消耗更多内存,尤其是对象较大或包含动态资源时。
- 特性:副本与原对象互不影响,适合需要独立数据的场景,但频繁拷贝会影响性能。
3. 移动(Move)
- 移动构造函数和移动赋值运算符用于高效转移资源所有权,避免不必要的深拷贝(C++11及以后)。
ClassName(ClassName&& other) noexcept;
ClassName& operator=(ClassName&& other) noexcept;
- 适用于管理动态资源的类,如智能指针、容器等。
- 移动操作后,源对象通常处于“空”或“有效但未定义”状态。
- 内存分配:通常不会分配新内存,而是“窃取”原对象的资源指针。
- 内存消耗:比拷贝更节省内存和时间,尤其适合管理动态资源的对象(如std::vector、std::string)。
- 特性:移动后,原对象处于“空”或“有效但未定义”状态,适合临时对象或需要转移资源所有权的场景。
4. 禁止拷贝(= delete)
- 通过将拷贝构造函数和拷贝赋值运算符声明为
= delete,可以禁止对象的拷贝和赋值。 - 适用于资源独占类,防止对象被无意复制导致的资源管理错误。
ExpressionParser(const ExpressionParser&) = delete;
ExpressionParser& operator=(const ExpressionParser&) = delete;
- 内存分配:无法进行拷贝操作,避免了不必要的内存分配和资源重复管理。
- 内存消耗:只允许唯一实例或移动,防止资源泄漏和重复释放。
- 特性:常用于资源独占类(如文件句柄、互斥锁、unique_ptr等),保证对象的唯一性和安全性。
5. 设计建议
- 对于需要唯一性或资源独占的类,建议禁止拷贝,支持移动。
- 对于需要共享资源的类,可以实现拷贝(如引用计数智能指针)。
- 使用
= delete明确禁止某些操作,有助于编译期发现错误,提升代码安全性和可维护性。
更多推荐


所有评论(0)