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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值