C++ 特殊成员函数详解:构造、析构、拷贝与移动
C 特殊成员函数详解构造、析构、拷贝与移动目录概述基础成员函数默认构造函数虚析构函数拷贝操作拷贝构造函数拷贝赋值运算符移动操作C11移动构造函数移动赋值运算符常见问题解析为什么拷贝参数是const T为什么移动参数是T五法则与最佳实践概述在 C 中一个类可以定义六个特殊的成员函数用于控制对象的创建、复制、移动和销毁函数类型典型声明默认构造函数object_base();析构函数virtual ~object_base();拷贝构造函数object_base(const object_base other);拷贝赋值运算符object_base operator(const object_base other);移动构造函数object_base(object_base other);移动赋值运算符object_base operator(object_base other);正确实现这些函数是编写高效、安全 C 代码的基础。基础成员函数默认构造函数object_base();创建对象时不带任何参数通常用于初始化成员变量为默认值如果用户未声明任何构造函数编译器会自动生成虚析构函数virtual~object_base();关键作用通过基类指针删除派生类对象时确保派生类的析构函数被调用若类有任何虚函数析构函数也应声明为virtual否则可能引起资源泄漏classBase{public:virtual~Base(){}};classDerived:publicBase{/* 动态分配的资源 */};Base*pnewDerived();deletep;// 若无虚析构仅调用 ~Base()Derived 部分资源泄露拷贝操作拷贝构造函数object_base(constobject_baseother);用已存在的对象创建新对象深拷贝调用时机函数按值传递对象函数按值返回对象直接用另一个对象初始化新对象Object a(b);或Object a b;拷贝赋值运算符object_baseoperator(constobject_baseother);将已存在对象的值赋给另一个已存在的对象需要处理自赋值this ! other典型实现深拷贝classString{char*data;size_t len;public:// 拷贝构造String(constStringother):len(other.len){datanewchar[len1];std::copy(other.data,other.datalen1,data);}// 拷贝赋值Stringoperator(constStringother){if(this!other){delete[]data;lenother.len;datanewchar[len1];std::copy(other.data,other.datalen1,data);}return*this;}};移动操作C11移动语义允许转移资源所有权而非复制从而大幅提升性能。移动构造函数object_base(object_baseother)noexcept;从右值临时对象或std::move转换的对象“窃取”资源将other置于“有效但未指定”的状态通常置空移动赋值运算符object_baseoperator(object_baseother)noexcept;释放当前资源转移other的资源给自己典型实现资源转移classString{char*data;size_t len;public:// 移动构造String(Stringother)noexcept:data(other.data),len(other.len){other.datanullptr;other.len0;}// 移动赋值Stringoperator(Stringother)noexcept{if(this!other){delete[]data;dataother.data;lenother.len;other.datanullptr;other.len0;}return*this;}};常见问题解析为什么拷贝参数是const T避免无限递归如果按值传递Object(Object other)调用拷贝构造时需要拷贝实参这将再次调用拷贝构造 → 无限递归。引用传递不会触发拷贝。性能按值传递会产生额外的临时拷贝浪费资源。语义正确拷贝不应修改原对象const保证了这一点且可接受临时对象。为什么移动参数是T区分左右值const T能绑定任何值左值、右值T只能绑定右值临时对象或std::move的结果通过重载编译器可以根据实参类型自动选择拷贝左值或移动右值。需要修改源对象移动操作会“窃取”源对象的资源必须将其指针置空或状态转移因此参数不能是const。性能优化移动操作通常是 O(1) 的指针赋值拷贝可能是 O(n) 的深拷贝。右值引用明确表示“这个对象即将销毁可以放心偷走它的资源”。为什么不是const Tconst T无法修改源对象无法实现资源转移毫无意义。对比表特性拷贝操作 (const T)移动操作 (T)参数类型const TT能否绑定左值✅❌需要std::move能否绑定右值✅✅是否修改源对象❌✅源对象状态不变有效但未指定通常为空性能昂贵深拷贝廉价指针复制五法则与最佳实践五法则Rule of Five如果类需要自定义析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符中的任何一个通常需要定义全部五个或明确default/delete。移动操作标记noexceptObject(Objectother)noexcept;Objectoperator(Objectother)noexcept;告知标准库该操作不会抛出异常容器如std::vector扩容时优先使用移动而非拷贝获得异常安全保证自赋值安全拷贝赋值和移动赋值都应检查if (this ! other)避免对同一对象操作。移动后状态被移动的对象必须处于可析构、可赋值的状态例如指针置空、长度归零但不保证其原值。编译器自动生成规则C11/17若用户声明了拷贝操作则不会生成移动操作反之亦然若用户声明了析构函数则不会自动生成拷贝/移动操作可能引起潜在问题建议显式使用default或delete控制特殊成员函数classSimple{public:Simple()default;virtual~Simple()default;Simple(constSimple)default;Simpleoperator(constSimple)default;Simple(Simple)default;Simpleoperator(Simple)default;};总结拷贝操作使用const T执行深拷贝不修改源对象。移动操作使用T转移资源所有权修改源对象性能高。虚析构函数基类必须声明以确保多态删除正确。五法则管理动态资源的类应完整定义或禁用这些特殊成员。noexcept移动帮助标准库优化提供强异常安全保证。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2607227.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!