左引用和右引用 右引用有什么用?( 二 )

class Object{ private: enum{ NAME_LEN = 50,}; public: Object(): Name(new char[NAME_LEN]){} Object(const char *NameStr); ~Object(); Object(const Object& B); /Object& operator=(const Object& B); /Object(Object&& B); Object& operator=(Object&& B); /移动赋值运算符 void Print(); bool NameIsEmpty(); private: char *Name; };
   我们新建一个Object类,有char*类型Name成员变量,我们在构造函数中申请内存,复制传入的字符串,并在构造函数中释放内存 。这主要是为了突出复制和移动之间的区别 。
实现复制构造函数和复制赋值运算符源码:
   Object::Object(const Object& B) { if(this == &B){ return; } Name = new char[NAME_LEN]; memcpy(Name,B.Name,strlen(B.Name)); std::cout << "Object copy constructor" << std::endl; } Object& Object::operator=(const Object& B) { if(this == &B){ return *this; } memset(Name,0,NAME_LEN); memcpy(Name,B.Name,strlen(B.Name)); std::cout << "Object copy assignment" << std::endl; return *this; }
   实现移动构造函数和移动赋值运算符源码:
   Object::Object(Object&& B) { //防止自我移动if(this == &B){ return; } Name = B.Name; B.Name = nullptr; std::cout << "Object move constructor" << std::endl; } Object& Object::operator=(Object&& B) { //防止自我移动if(this == &B){ return *this; } if(!Name){ delete[] Name; } Name = B.Name; B.Name = nullptr; std::cout << "Object move assignment" << std::endl; return *this; }
   移动结构函数和移动赋值运算符已经实现,可以使用std::move()标准库函数将左值转换为右值并调用它们 。让我们用代码示例来看看如何使用它std::move()库函数,并调用我们实现的移动构造函数和移动赋值运算符 。
   Object B1("Tangmeimei"); Object B2(B1); //调用复制构造函数 B2 = B1; B1.Print(); B2.Print(); Object B4(std::move(B2)); if(B2.NameIsEmpty()){ std::cout << "B2 Object name is empty" << std::endl; } B4.Print(); Object B3; B3 = std::move(B1); if(B1.NameIsEmpty()){ std::cout << "B1 Object name is empty" << std::endl; } B3.Print();
   操作结果及总结    

左引用和右引用 右引用有什么用?

文章插图
   移动和复制代码示例运行结果
   从操作结果可以看出,调用复制结构函数和复制赋值运算符最多会经历一次内存释放、一次内存申请和一次数据复制 。调用移动结构函数和移动赋值运算符最多会经历一次内存释放 。因此,数据的移动远远超过数据的复制能高,移动将使源对象失去资源的所有权 。
   下一期我们会详细讲解,C 引用折叠和完美转发 。