练习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节练习相关推荐

  1. C++primer 13.1.6节练习

    练习13.18 1 #include <iostream> 2 #include <string> 3 #include <memory> 4 5 using na ...

  2. 《C++ Primer》13.1.3节练习

    练习13.9: 析构函数完成与构造函数相反的工作:释放对象使用的资源,销毁非静态数据成员.从语法上看,它是类的一个成员函数,名字是波浪号接类名,没有返回值,也不接受参数. 当一个类没有定义析构函数时, ...

  3. 《C++ Primer》13.1.2节练习

    练习13.6: 拷贝赋值运算符本身是一个重载的赋值运算符,定义为类的成员函数,左侧运算对象绑定到隐含的this参数,而右侧运算对象是所属类类型的,作为函数的参数,函数返回指向其左侧运算对象的引用. 当 ...

  4. 《C++ Primer》13.1.1节练习

    练习13.1: 如果构造函数的第一个参数是自身类类型的引用,且所有其他参数(如果有的话)都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数在以下几种情况下会被使用: ●拷贝初始化(用=定义变量). ...

  5. 《C++ Primer》13.1.6节练习(部分)

    练习13.18: #include <iostream> #include <string> using namespace std;class Employee {priva ...

  6. 《C++ Primer》13.1.4节练习

    练习13.14: 这是一个典型的应该定义拷贝控制成员的场合.如果不定义拷贝构造函数和拷贝赋值运算符,依赖合成的版本,则在拷贝构造和赋值时,会简单复制数据成员.对本问题来说,就是将序号简单复制给新对象. ...

  7. 【C++ Primer | 13】课后习题答案

    文章目录 13.1.4节目练习 13.2节练习 13.2.2练习 13.1.4节目练习 练习13.14 #include <iostream> using namespace std;cl ...

  8. C++primer 9.2.1节练习

    练习9.3 迭代器begin和end必须指向相同的容器,end可以与begin指向相同的位置,但不能指向begin之前的位置: 练习9.4 1 #include <iostream> 2 ...

  9. C++primer 10.2.1节练习

    练习10.3 1 #include<iostream> 2 #include<string> 3 #include<vector> 4 #include <s ...

最新文章

  1. 第五次作业 何雅
  2. MIT设计深度学习框架登Nature封面,预测非编码区DNA突变
  3. json-lib把XML转化为json
  4. IC/FPGA校招笔试题分析(三)
  5. 漳州市2021高考成绩查询,漳州市招生管理系统2021漳州中考成绩查询入口
  6. SAP Spartacus运行时错误 - The pipe cxUrl could not be found!
  7. 文本文件 java_Java入门:读写文本文件
  8. Engineer05
  9. linux amd显卡调风扇转速,从调软件到改BIOS 显卡帝玩转风扇转速
  10. BackTrack 3下使用spoonwep2破解WEP加密的无线路由器
  11. Ansys许可重新配置
  12. excel白屏未响应_EXCEL2016经常卡死,白屏,经常使用过程中卡住,然后显示office正在尝试恢复...
  13. 单片机基础教程那么多,什么样才是靠谱的学习方式
  14. Android Banner图片轮播
  15. android 车载蓝牙音乐介绍
  16. 果粉沸腾,iPhone6领衔苹果最顶级明星阵容
  17. 拼多多后台x4.0监控mysql_11、ABPZero系列教程之拼多多卖家工具 拼团提醒功能页面实现...
  18. win8文件操作以及音视频的应用
  19. 四川大学计算机博士申请考核条件,四川大学2020年博士招生章程发布!招1650人!...
  20. 知识星球爬虫2023-2-9

热门文章

  1. python决策树id3算法_python实现决策树ID3算法
  2. Java多线程_1_Java内存模型_内存模型的3大特性
  3. matplotlib 散点图_matplotlib画图 绘制散点图案例
  4. python提取txt中的字符串数据_python 从字符串中提取数值
  5. Web框架——Flask系列之宏、继承、包含(十八)
  6. 论文阅读 - Group Normalization
  7. LeetCode 432. 全 O(1) 的数据结构(设计题)*
  8. LeetCode 1037. 有效的回旋镖
  9. LeetCode 51. N皇后 / 52. N皇后 II(回溯)
  10. java 拦截器_Spring的春天来啦——百战Java课程更新(2019.09.06)