C++ 移动构造与移动赋值:类成员变量处理方式

张开发
2026/5/4 23:23:39 15 分钟阅读
C++ 移动构造与移动赋值:类成员变量处理方式
移动构造与移动赋值中类成员变量处理方式相同此处以移动构造为例子。首先写一个类包含类中所有可能的成员变量类型基础值int、float、bool、char…裸指针T*类std::string、vector、自己写的类…智能指针unique_ptr、shared_ptr左值引用T首先我们创建一个类并且包含上述所有类型的成员变量classMyClass{// 自定义类包含移动构造函数这里省略了......};classTestClass{public:TestClass(intref_num):num_{1},ptr_{newint(10)},vec_{1,2,3},my_class_{MyClass()},u_ptr_{std::make_uniqueint(20)},s_ptr_{std::make_sharedint(30)},ref_num_{ref_num}{std::coutdefault constructor\n;}// 移动构造TestClass(TestClassother)noexcept{std::coutmove constructor\n;}~TestClass(){deleteptr_;// 裸指针需要手动释放ptr_nullptr;std::coutdestructor\n;}private:intnum_;// 基础类型int*ptr_;// 裸指针std::vectorintvec_;// 标准库容器类MyClass my_class_;// 自定义类std::unique_ptrintu_ptr_;// 独占智能指针std::shared_ptrints_ptr_;// 共享智能指针intref_num_;// 左值引用};其中移动构造函数我们先保持什么都不做下面分别给出每种类型处理方式。1. 基础值int、float、bool、char…基础值类型没有移动的概念只能直接拷贝数据。// 移动构造TestClass(TestClassother)noexcept:num_{other.num_}// 基础数据类型直接拷贝值{std::coutmove constructor\n;// 把原对象置为安全状态other.num_0;}2. 裸指针T*对于裸指针不需要拷贝指针指向的数据直接拷贝指针地址。// 移动构造TestClass(TestClassother)noexcept:ptr_{other.ptr_}// 裸指针直接拷贝指针地址不拷贝指向的数据{std::coutmove constructor\n;// 把原对象置为安全状态other.ptr_nullptr;}3. 类string、vector、自定义类无论是标准库中的类还是自定义的类使用std::move直接交给类本身的移动构造函数转移内部资源类成员变量处理方式和本文相同。// 移动构造TestClass(TestClassother)noexcept:vec_{std::move(other.vec_)},// 标准库容器vector调用vector的移动构造高效转移内部内存my_class_{std::move(other.my_class_)},// 自定义类调用自定义类的移动构造转移其内部资源{std::coutmove constructor\n;}4. 智能指针unique_ptr /shared_ptr不论是unique_prt独占指针还是shared_prt共享指针都使用std::move转移所有权当然shared_prt虽然转移了所有权但是本身不改变引用计数。本质仍然是调用了其内部的移动构造函数。// 移动构造TestClass(TestClassother)noexcept:u_ptr_{std::move(other.u_ptr_)},// unique_ptr独占智能指针转移所有权s_ptr_{std::move(other.s_ptr_)},// shared_ptr转移所有权但移动不改变引用计数{std::coutmove constructor\n;}5. 左值引用T引用类型只能拷贝不能移动和重新绑定。// 移动构造TestClass(TestClassother)noexcept:ref_num_{other.ref_num_}// 左值引用引用无法移动/重新绑定只能拷贝{std::coutmove constructor\n;}这里贴出完整代码大家可以打断点调试查看资源转移情况#includeiostream#includevector#includememoryclassMyClass{// 自定义类包含移动构造函数这里省略了......};classTestClass{public:TestClass(intref_num):num_{1},ptr_{newint(10)},vec_{1,2,3},my_class_{MyClass()},u_ptr_{std::make_uniqueint(20)},s_ptr_{std::make_sharedint(30)},ref_num_{ref_num}{std::coutdefault constructor\n;}// 移动构造TestClass(TestClassother)noexcept:num_{other.num_},// 基础数据类型直接拷贝值ptr_{other.ptr_},// 裸指针直接拷贝指针地址不拷贝指向的数据vec_{std::move(other.vec_)},// 标准库容器vector调用vector的移动构造高效转移内部内存my_class_{std::move(other.my_class_)},// 自定义类调用自定义类的移动构造转移其内部资源u_ptr_{std::move(other.u_ptr_)},// unique_ptr独占智能指针转移所有权s_ptr_{std::move(other.s_ptr_)},// shared_ptr转移所有权但移动不改变引用计数ref_num_{other.ref_num_}// 左值引用引用无法移动/重新绑定只能拷贝{std::coutmove constructor\n;// 把原对象置为安全状态other.ptr_nullptr;other.num_0;}~TestClass(){deleteptr_;// 裸指针需要手动释放ptr_nullptr;std::coutdestructor\n;}private:intnum_;// 基础类型int*ptr_;// 裸指针std::vectorintvec_;// 标准库容器类MyClass my_class_;// 自定义类std::unique_ptrintu_ptr_;// 独占智能指针std::shared_ptrints_ptr_;// 共享智能指针intref_num_;// 左值引用};intmain(){intnum{1};TestClass test_default{num};// 默认构造TestClass test_move{std::move(test_default)};// 移动构造std::coutProgram finished!\n;return0;}

更多文章