标签:
移动语义--std::move
a. 字符串的定义
b. ArrayWrapper
String.cc
1 #include<iostream> 2 #include<string.h> 3 4 class String 5 { 6 public: 7 String() 8 { 9 std::cout << “String()” << std::endl; 10 pstr_ = new char[1]; 11 } 12 13 String(const char *pstr) 14 { 15 std::cout << “String(const char *pstr)” << std::endl; 16 pstr_ = new char[strlen(pstr) + 1]; 17 strcpy(pstr_ , pstr); 18 } 19 20 String(const String &rhs) //复制构造函数 21 { 22 std::cout << “String(const String &rhs)” << std::endl; 23 pstr_ = new char[strlen(rhs.pstr_) + 1]; 24 strcpy(pstr_, rhs.pstr_); 25 } 26 27 String(String &&rhs) //移动构造函数,移动就意味着修改,所以不加const。当发现是右值时,会优先绑定移动构造函数。 28 : pstr_(rhs.pstr_) 29 { 30 std::cout << “String(String &&rhs)” << std::endl; 31 rhs.pstr_ = NULL; 32 } 33 34 String &operator=(String &&rhs) //移动赋值运算符函数 35 { 36 std::cout << “String &operator=(String &&rhs)” << std::endl; 37 if(this != &rhs) 38 { 39 delete []pstr_; 40 pstr_ = rhs.pstr_; 41 rhs.pstr_ = NULL; 42 } 43 return *this; 44 } 45 46 String &operator=(const String &rhs) //赋值运算符函数 47 { 48 std::cout << “String &operator=(const String &rhs)” << std::endl; 49 if(this != &rhs) 50 { 51 delete []pstr_; 52 pstr_ = new char[strlen(rhs.pstr_) + 1]; 53 strcpy(pstr_ , rhs.pstr_); 54 } 55 return *this; 56 } 57 58 String & operator += (const String &rhs) 59 { 60 std::cout << “String & operator+=(const String &rhs) ” <<std::cout; 61 int len = strlen(pstr_) + strlen(rhs.pstr_) + 1; 62 char * ptmp = new char[len+1]; 63 strcpy(ptmp, pstr_); 64 strcat(ptmp, rhs.pstr_); 65 66 return *this; 67 } 68 69 ~String() 70 { 71 if(pstr_) 72 std::cout << “~String() pstr_ = ” << std::hex << reinte << std::endl; 73 else 74 std::cout << “~String() pstr_ = NULL” << std::endl; 75 delete []pstr_; 76 } 77 78 friend std::ostream &operator<<(std::ostream &os, const String &rhs); 79 private: 80 char *pstr_; 81 }; 82 83 String operator + (const String &lhs, const String &rhs) 84 { 85 std::cout << “String operator + (const String &lhs, const String &rhs)” <<std::endl; 86 String tmp(lhs); 87 tmp += rhs; 88 89 return tmp; 90 } 91 92 String operator+(const String &lhs, const char *rhs) 93 { 94 std::cout << “String operator + (const String &lhs, const char *rhs)” <<std::endl; 95 String tmp(rhs); 96 tmp += lhs; 97 98 return tmp; 99 } 100 101 String operator+(const char *lhs, const String &rhs) 102 { 103 std::cout << “String operator + (const char *lhs, const String &rhs)” <<std::endl; 104 String tmp(lhs); 105 tmp += rhs; 106 107 return tmp; 108 } 109 110 std::ostream &operator<<(std::ostream &os, const String &rhs) 111 { 112 os<<rhs.pstr_; 113 return os; 114 } 115 116 String getStr() 117 { 118 std::cout << “==========” <<std::endl; 119 String s1 = “hello”; 120 return s1; 121 } 122 123 int main(void) 124 { 125 String s1 = “hello world”; //调用有参构造函数, 还会优先调用移动构造函数 126 //hello world 通过隐式转换会生成一个String的临时对象,这个临时对象就是一个右值, 右值会优先绑定到右值引用,调用 移动构造函数,而不是去调用 复制构造函数。如果没有 移动构造函数, 就会调用 复制构造函数 ,因为复制构造函数 的参数是 常量左值引用,它可以绑定到所有类型的值,包括 非常量左值、常量左值、右值。 127 128 std::cout << “移动构造函数” << std::endl; 129 getStr(); 130 std::cout << “-------------” << std::endl; 131 132 String s3 = s1 + s2; // 会调用 构造函数、赋值运算符函数、+=运算符函数 、 移动赋值运算符函数 和 析构函数, 优先调用移动赋值运算符函数的原因是:发生了右值赋值给了左值。 133 134 return 0; 135 }
Std_move.cc
1 #include<iostream> 2 #include<string> 3 4 class MetaData 5 { 6 public: 7 MetaData(int size, const std::string &name) 8 :size_(size), name_(name) 9 { 10 std::cout << “MetaData(int size, const std::string &name)” <<std::endl; 11 } 12 13 MetaData(const MetaData &other) 14 :name_(other.name_), size_(other.size_) 15 { 16 std::cout << “MetaData(const MetaData &other)” <<std::endl; 17 } 18 19 MetaData(MetaData &&other) //移动构造函数 , 不加const 20 //: name_(other.name_) // std::string 的复制构造函数 21 : name_(std::move(other.name_)), size_(other.size_) 22 { 23 std::cout << “MetaData(MetaData &&other)” <<std::endl; 24 } 25 26 std::String getName() const 27 { 28 return name_; 29 } 30 31 int getSize() const 32 { 33 return size_; 34 } 35 36 private: 37 std::string name_; 38 int size_; 39 }; 40 41 class ArrayWrapper 42 { 43 public: 44 ArrayWrapper() 45 : pVals_(new int[64]), metadata_(64, “ArrayWrapper”) 46 { 47 std::cout << “ArrayWrapper()” << std::endl; 48 } 49 50 ArrayWrapper(int n) 51 : pVals_(new int[n]), metadata_(n, “ArrayWrapper”) 52 { 53 std::cout << “ArrayWrapper(int n)” << std::endl; 54 } 55 56 ArrayWrapper(const ArrayWrapper &other) 57 : pVals_(new int[other.metadata_.getSize()]), metadata_(other.metadata_) 58 { 59 std::cout << “ArrayWrapper(const ArrayWrapper &other)” << std::endl; 60 for(inti dx = 0; idx != other.metadata_.size_; ++idx) 61 { 62 pVals_[idx] = other.pVals_[idx]; 63 } 64 } 65 66 ArrayWrapper (ArrayWrapper &&other) //移动构造函数 , 不加const 67 : pVals_(other.pVals_), 68 //metadata_(other.metadata_) //other.metadata_本身是一个左值,会调用Metadata类的复制构造函数,与这里的初衷有相违背的地方,外层是移动构造,内层也得是移动构造,这种语义才算正常,要不然不是真正的移动构造语义。所以要换成 移动构造。 69 metadata_(std::move(other.metadata_)) //这里会调用Metadata的移动构造函数。 70 { 71 std::cout << “ArrayWrapper(ArrayWrapper &&other)” << std::endl; 72 other.pVals_ = NULL; 73 } 74 75 ~ ArrayWrapper() 76 { 77 std::cout << “~ArrayWrapper()” << std::endl; 78 delete []pVals_; 79 } 80 81 private: 82 int *pVals_; 83 MetaData metadata_; 84 }; 85 86 int main(void) 87 { 88 ArrayWrapper aw1; 89 std::cout << “移动构造函数” << std::endl; 90 ArrayWrapper aw2(std::move(aw1)); //使用std::move将aw1变成一个右值应用,传给移动构造函数。 91 92 return 0; 93 }
标签:
原文地址:http://www.cnblogs.com/jianhui-Ethan/p/4668715.html