C++primer 13.6.2节练习
练习13.49 13.50
1 #include <iostream> 2 #include <string> 3 #include <utility> 4 #include <memory> 5 #include <algorithm> 6 #include <vector> 7 8 using namespace std; 9 10 class String { 11 friend ostream &print(ostream &os, String &s); 12 public: 13 String(): element(nullptr), first_free(nullptr) {} 14 String(char *); 15 size_t size() const{ return first_free - element; } 16 String(const String&); 17 String& operator=(const String&); 18 String(String&&) noexcept; 19 String& operator=(String&&) noexcept; 20 ~String() { free(); } 21 private: 22 static allocator<char> alloc; 23 pair<char *, char *> alloc_n_copy(const char*, const char *); 24 void free(); 25 char *element; 26 char *first_free; 27 }; 28 allocator<char> String::alloc; 29 ostream &print(ostream &os, String &s); 30 31 int main() 32 { 33 vector<String> vec; 34 String s1("hello"); 35 String s2("world"); 36 String s3(s1); 37 String s4 = s2; 38 s3 = s1; 39 String s5 = std::move(s4); 40 vec.push_back(s1); 41 vec.push_back(s2); 42 vec.push_back(s3); 43 vec.push_back(s4); 44 vec.push_back(s5); 45 system("pause"); 46 return 0; 47 } 48 49 String::String(char *s) 50 { 51 int i = 0; 52 while (s[i] != '\0') 53 i = i + 1; 54 auto newloc = alloc.allocate(i); 55 auto dest = newloc; 56 for (auto count = 0; count != i;++count) 57 alloc.construct(dest++, s[count]); 58 element = newloc; 59 first_free = dest; 60 cout << "普通构造函数" << endl; 61 } 62 63 String::String(const String &s) 64 { 65 auto newdata = alloc_n_copy(s.element, s.first_free); 66 element = newdata.first; 67 first_free = newdata.second; 68 cout << "拷贝构造函数" << endl; 69 } 70 71 String & String::operator=(const String &rhs) 72 { 73 auto newdata = alloc_n_copy(rhs.element, rhs.first_free); 74 free(); 75 element = newdata.first; 76 first_free = newdata.second; 77 cout << "拷贝赋值运算符" << endl; 78 return *this; 79 // TODO: 在此处插入 return 语句 80 } 81 82 String::String(String &&s) noexcept : element(s.element), first_free(s.first_free) { s.element = s.first_free = nullptr; cout << "移动构造函数" << endl; } 83 84 String & String::operator=(String &&rhs) noexcept 85 { 86 if (this != &rhs) 87 { 88 element = rhs.element; 89 first_free = rhs.first_free; 90 rhs.element = rhs.first_free = nullptr; 91 } 92 cout << "移动赋值运算符" << endl; 93 return *this; 94 // TODO: 在此处插入 return 语句 95 } 96 97 pair<char*, char*> String::alloc_n_copy(const char *b, const char *e) 98 { 99 auto data = alloc.allocate(e - b); 100 return{ data,uninitialized_copy(b,e,data) }; 101 } 102 103 void String::free() 104 { 105 if (element) 106 { 107 for (auto p = first_free; p != element;) 108 alloc.destroy(--p); 109 alloc.deallocate(element,first_free - element); 110 } 111 } 112 113 ostream & print(ostream &os,String &s) 114 { 115 while (s.element != s.first_free) 116 { 117 os << *(s.element); 118 s.element++; 119 } 120 cout << endl; 121 return os; 122 // TODO: 在此处插入 return 语句 123 }
其他的移动构造函数和移动赋值运算符的写法类似,注意两点,一点是加上noexcept,还有一点事注意最后移动后原对象的安全释放。
练习13.51
我们可以拷贝或赋值一个将要销毁的unique_ptr,由于返回的值是一个临时对象,故他是一个右值绑定的引用,这里的拷贝和赋值是移动拷贝和移动赋值,他不是正常的拷贝,而是窃取资源。
练习13.52
两者的区别在于刚开始的将hp2赋值给rhs的过程,第一个调用拷贝构造函数,分配新内存,将hp2完全拷贝给rhs,这时就有两个一样的对象,而第二个式子是调用移动构造函数,他从hp2拷贝指针,而不会重新分配内存,再将原对象的指针置空,后面的操作都类似了。
练习13.53
注意拷贝赋值运算符由于是拷贝的原因移后源对象依然存在且不变,而移动赋值运算符移后源对象虽然在但是一般为了正确释放会置空;
1 HasPtr& operator=(HasPtr& rhs){ 2 delete ps; 3 swap(*this,rhs); 4 cout<<"HasPtr& operator=(HasPtr& rhs)"<<endl; 5 return *this; 6 } 7 HasPtr& operator=(HasPtr&& rhs){ 8 ps=std::move(rhs.ps); 9 i=std::move(rhs.i); 10 rhs.ps=nullptr;
1 #include <iostream> 2 #include <string> 3 #include <memory> 4 #include <vector> 5 #include <algorithm> 6 #include <numeric> 7 8 using namespace std; 9 10 class HasPtr { 11 friend ostream &print(ostream &os, HasPtr &h); 12 friend void swap(HasPtr &lhs, HasPtr &rhs); 13 friend bool operator<(HasPtr &lpt, HasPtr &rpt); 14 friend string & out(HasPtr &pt); 15 public: 16 HasPtr(const string &s = string()) : ps(new string(s)), i(0) {} 17 HasPtr(const HasPtr &ptr); 18 HasPtr &operator=(const HasPtr &pt); 19 HasPtr &operator=(HasPtr &&) noexcept; 20 ~HasPtr() { delete ps; } 21 22 private: 23 string *ps; 24 int i; 25 }; 26 27 ostream &print(ostream &os, HasPtr &h); 28 inline void swap(HasPtr &lhs, HasPtr &rhs); 29 bool operator<(HasPtr &lpt, HasPtr &rpt); 30 string & out(HasPtr &pt); 31 32 int main() 33 { 34 vector<HasPtr> svec; 35 string word; 36 while (cin >> word) 37 { 38 svec.push_back(*new HasPtr(word)); 39 } 40 sort(svec.begin(), svec.end()); 41 for (auto c : svec) 42 { 43 cout << out(c) << endl; 44 } 45 system("pause"); 46 return 0; 47 } 48 49 HasPtr::HasPtr(const HasPtr & ptr) : ps(new string(*(ptr.ps))), i(ptr.i) {} 50 51 HasPtr & HasPtr::operator=(const HasPtr & pt) 52 { 53 auto q = new string(*pt.ps); 54 delete ps; 55 ps = q; 56 i = pt.i; 57 cout << "0" << endl; 58 return *this; 59 } 60 61 HasPtr & HasPtr::operator=(HasPtr &&pt) noexcept 62 { 63 if (this != &pt) 64 { 65 delete ps; 66 ps = pt.ps; 67 i = pt.i; 68 pt.ps = nullptr; 69 } 70 cout << "1" << endl; 71 return *this; 72 // TODO: 在此处插入 return 语句 73 } 74 75 string & out(HasPtr & pt) 76 { 77 return *pt.ps; 78 } 79 80 bool operator<(HasPtr & lpt, HasPtr &rpt) 81 { 82 return (*lpt.ps).size() < (*rpt.ps).size(); 83 } 84 85 ostream & print(ostream & os, HasPtr & h) 86 { 87 os << *h.ps << h.i << endl; 88 return os; 89 } 90 91 inline void swap(HasPtr & lhs, HasPtr & rhs) 92 { 93 using std::swap; 94 swap(lhs.ps, rhs.ps); 95 cout << "ps already copy" << endl; 96 swap(lhs.i, rhs.i); 97 cout << "i already copy" << endl; 98 }
程序运行时没有调用拷贝赋值运算符,而是调用的移动赋值运算符,根据网上答案,应该和编译器有关。
11 cout<<"HasPtr& operator=(HasPtr&& rhs)"<<endl; 12 return *this; 13 }
练习13.54
转载于:https://www.cnblogs.com/wuyinfenghappy/p/7481774.html
C++primer 13.6.2节练习相关推荐
- C++primer 13.1.6节练习
练习13.18 1 #include <iostream> 2 #include <string> 3 #include <memory> 4 5 using na ...
- 《C++ Primer》13.1.3节练习
练习13.9: 析构函数完成与构造函数相反的工作:释放对象使用的资源,销毁非静态数据成员.从语法上看,它是类的一个成员函数,名字是波浪号接类名,没有返回值,也不接受参数. 当一个类没有定义析构函数时, ...
- 《C++ Primer》13.1.2节练习
练习13.6: 拷贝赋值运算符本身是一个重载的赋值运算符,定义为类的成员函数,左侧运算对象绑定到隐含的this参数,而右侧运算对象是所属类类型的,作为函数的参数,函数返回指向其左侧运算对象的引用. 当 ...
- 《C++ Primer》13.1.1节练习
练习13.1: 如果构造函数的第一个参数是自身类类型的引用,且所有其他参数(如果有的话)都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数在以下几种情况下会被使用: ●拷贝初始化(用=定义变量). ...
- 《C++ Primer》13.1.6节练习(部分)
练习13.18: #include <iostream> #include <string> using namespace std;class Employee {priva ...
- 《C++ Primer》13.1.4节练习
练习13.14: 这是一个典型的应该定义拷贝控制成员的场合.如果不定义拷贝构造函数和拷贝赋值运算符,依赖合成的版本,则在拷贝构造和赋值时,会简单复制数据成员.对本问题来说,就是将序号简单复制给新对象. ...
- 【C++ Primer | 13】课后习题答案
文章目录 13.1.4节目练习 13.2节练习 13.2.2练习 13.1.4节目练习 练习13.14 #include <iostream> using namespace std;cl ...
- C++primer 9.2.1节练习
练习9.3 迭代器begin和end必须指向相同的容器,end可以与begin指向相同的位置,但不能指向begin之前的位置: 练习9.4 1 #include <iostream> 2 ...
- C++primer 10.2.1节练习
练习10.3 1 #include<iostream> 2 #include<string> 3 #include<vector> 4 #include <s ...
最新文章
- 第五次作业 何雅
- MIT设计深度学习框架登Nature封面,预测非编码区DNA突变
- json-lib把XML转化为json
- IC/FPGA校招笔试题分析(三)
- 漳州市2021高考成绩查询,漳州市招生管理系统2021漳州中考成绩查询入口
- SAP Spartacus运行时错误 - The pipe cxUrl could not be found!
- 文本文件 java_Java入门:读写文本文件
- Engineer05
- linux amd显卡调风扇转速,从调软件到改BIOS 显卡帝玩转风扇转速
- BackTrack 3下使用spoonwep2破解WEP加密的无线路由器
- Ansys许可重新配置
- excel白屏未响应_EXCEL2016经常卡死,白屏,经常使用过程中卡住,然后显示office正在尝试恢复...
- 单片机基础教程那么多,什么样才是靠谱的学习方式
- Android Banner图片轮播
- android 车载蓝牙音乐介绍
- 果粉沸腾,iPhone6领衔苹果最顶级明星阵容
- 拼多多后台x4.0监控mysql_11、ABPZero系列教程之拼多多卖家工具 拼团提醒功能页面实现...
- win8文件操作以及音视频的应用
- 四川大学计算机博士申请考核条件,四川大学2020年博士招生章程发布!招1650人!...
- 知识星球爬虫2023-2-9
热门文章
- python决策树id3算法_python实现决策树ID3算法
- Java多线程_1_Java内存模型_内存模型的3大特性
- matplotlib 散点图_matplotlib画图 绘制散点图案例
- python提取txt中的字符串数据_python 从字符串中提取数值
- Web框架——Flask系列之宏、继承、包含(十八)
- 论文阅读 - Group Normalization
- LeetCode 432. 全 O(1) 的数据结构(设计题)*
- LeetCode 1037. 有效的回旋镖
- LeetCode 51. N皇后 / 52. N皇后 II(回溯)
- java 拦截器_Spring的春天来啦——百战Java课程更新(2019.09.06)