c++primer(第五版) 第十三章 拷贝控制习题答案
来源:互联网 发布:造梦西游4修改器mac版 编辑:程序博客网 时间:2024/05/18 17:57
纯原创 转载请注明出处:http://blog.csdn.net/axuan_k
13.2 13.3 13.4 13.5
#include<iostream>using namespace std;class Point{ int a;};Point global; //13.4Point foo_bar(Point arg) //1{ Point local = arg, *heap = new Point(global); //2,3 *heap = local; Point pa[ 4 ] = { local, *heap }; //4,5 return *heap; //6}class HasPtr{public: HasPtr(const string&s=string()):ps(new string(s)),i(0){} HasPtr(const HasPtr& hp):ps(new string(*hp.ps)),i(hp.i){} // 13.5private: string *ps; int i;};int main(){// 13.2// 拷贝构造函数的参数如果是实参,那就需要在调用它的时候复制 原对象给它,// 而这个复制过程又需要调用拷贝构造函数才能完成,如此无限循环// 13.3// StrBlob中智能share指针指向的对象的use_count会+1// 而StrBlobPtr中智能weak指针指向的use_count不会变// 是share指针和weak指针的性质决定的 return 0;}
13.6 13.7 13.8
#include<iostream>using namespace std;class HasPtr{public: HasPtr(const string&s=string()):ps(new string(s)),i(0){} HasPtr(const HasPtr& hp):ps(new string(*hp.ps)),i(hp.i){} HasPtr& operator=(const HasPtr& hp){ //13.8 ps=new string(*hp.ps); i=hp.i; return *this; }private: string *ps; int i;};int main(){// 13.6// 拷贝赋值运算符: operator=// 当需要进行同类中对象的赋值时使用它// 完成 将右侧所有非static的成员赋予左侧运算对象的对应成员// 当用户未定义自己的拷贝赋值运算符时// 13.7// StrBlob赋值时 被赋值的StrBlob指向容器的use_count-1,赋值一方StrBlob指向容器的use_count+1// StrBlobPtr的两侧指向容器的use_count都不会变 return 0;}
13.9 13.10 13.11 13.12 13.13
#include<iostream>#include<vector>using namespace std;class HasPtr{public: HasPtr(const string&s=string()):ps(new string(s)),i(0){} HasPtr(const HasPtr& hp):ps(new string(*hp.ps)),i(hp.i){} HasPtr& operator=(const HasPtr& hp){ ps=new string(*hp.ps); i=hp.i; return *this; } ~HasPtr(){delete ps;} //13.11private: string *ps; int i;};struct X{ X(){cout<<"X()"<<endl;} X(const X& x){cout<<"X(const X& x)"<<endl;} X& operator=(const X& x){cout<<"X& operator=(const X& x)"<<endl; return *this;} ~X(){cout<<"~X()"<<endl;}};void func(const X& a,const X b){ vector<X>vec; cout<<"1111111111"<<endl; vec.push_back(a); cout<<"1111"<<endl; vec.push_back(b); cout<<1111<<endl;}int main(){// 13.9// 析构函数释放对象使用的资源,并销毁对象的非static成员// 合成析构函数可以用来阻止对象被销毁,否则函数体为空// 当用户未定义对应类的析构函数时// 13.10// StrBlob指向容器的use_count会-1,如果该容器use_count为0则会被销毁// 而StrBlobPtr指向容器的use_count不会变// 13.12// 共三次// bool fcn(const Sales_data *trans, Sales_data accum) //对象accum函数结束时销毁 +1次//{// Sales_data item1(*trans), item2(accum);// 对象item1 item2函数结束时销毁 +2次// return item1.isbn() != item2.isbn();//}// 13.13 X* a=new X; X* c=a; *c=*a; X d(*a); func(*a,d); return 0;}
13.14 13.15 13.16 13.17
#include<iostream>#include<vector>using namespace std;class numbered{public: numbered():mysn(get_id()){} numbered(const numbered& x):mysn(get_id()){} int get_id(){return ++num;} int mysn; static int num;};int numbered::num=0;void f(const numbered& x){cout<<x.mysn<<endl;}int main(){// 13.14// 输出全都是1,a是默认构造函数创建的,b,c是拷贝构造函数创建的 numbered a,b=a,c=b; f(a),f(b),f(c);// 13.15// 会 输出4 5 6// b,c都是通过我们自己定义的拷贝构造函数创建的// 当abc传参数给x时又会调用拷贝构造函数// 13.16// 会 输出1 2 3// 当f的参数为引用时,就不会调用拷贝构造函数 num也就不会+1// 13.17 return 0;}
13.18 13.19 13.20
#include<iostream>#include<vector>using namespace std;class Employee{ //13.18public: Employee()=default; Employee(const string& s):name(s),id(get_id()){} Employee(const Employee& e)=delete; Employee& operator=(const Employee& e)=delete;private: string name; int id; static int num; const int get_id()const{return ++num;}};int Employee::num=0;int main(){// 13.19// 需要 因为每个对象都应该有一个独立的id// 默认合成的拷贝构造函数和拷贝赋值函数都会复制id,不应该有拷贝和赋值的操作// 13.20// TextQuery和QueryResult所有成员(包括智能指针和容器)都将被拷贝 return 0;}
13.21
#ifndef MY_CLASS#define MY_CLASS#include<iostream>#include<sstream>#include<fstream>#include<map>#include<set>#include<vector>#include<string>#include<memory>class QueryResult;std::ostream& print(std::ostream&, const QueryResult&);class TextQuery {public: //typedef using line_no = std::vector<std::string>::size_type; //constructor TextQuery(std::ifstream&); //Query function QueryResult query(const std::string&) const; TextQuery(const TextQuery&) = delete; TextQuery& operator=(const TextQuery&) = delete;private: //data members std::shared_ptr<std::vector<std::string>> in_file; std::map<std::string, std::shared_ptr<std::set<line_no>>> word_occr;};//TextQuery constructorTextQuery::TextQuery(std::ifstream& input) : in_file(new std::vector<std::string>) { for (std::string text; getline(input, text); in_file->push_back(text)) { int cur_line_no = in_file->size() + 1; std::string word; for (std::istringstream line(text); line >> word; ) { auto &line_nums = word_occr[word]; if (!line_nums) line_nums.reset(new std::set<TextQuery::line_no>); line_nums->insert(cur_line_no); } }}class QueryResult { friend std::ostream& print(std::ostream&, const QueryResult&);public: //constructor QueryResult(std::string s, std::shared_ptr<std::vector<std::string>> f, std::shared_ptr<std::set<TextQuery::line_no>> l) : sought(s), file(f), lines(l) { } QueryResult(const QueryResult&) = delete; QueryResult& operator=(const QueryResult&) = delete; QueryResult(QueryResult &&) noexcept = default; //!! here!! //member functions std::set<TextQuery::line_no>::iterator begin() { return lines->begin(); } std::set<TextQuery::line_no>::iterator end() { return lines->end(); } std::shared_ptr<std::vector<std::string>> get_file() { return file; }private: //data members std::string sought; //word sought by this query std::shared_ptr<std::vector<std::string>> file; //file we are searching in std::shared_ptr<std::set<TextQuery::line_no>> lines; //lines sought is found on};QueryResult TextQuery::query(const std::string& s) const { static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>); auto found = word_occr.find(s); if (found == word_occr.end()) return QueryResult(s, in_file, nodata); else return QueryResult(s, in_file, found->second);}std::ostream& print(std::ostream& out, const QueryResult& qr) { out << qr.sought << " : " << qr.lines->size() << std::endl; return out;}#endif
13.24 13.25 13.26
#include<iostream>#include<vector>#include<string>#include<memory>#include<stdexcept>using namespace std;class StrBlob{public: typedef vector<string>::size_type size_type; StrBlob():data(make_shared<vector<string>>()){} StrBlob(initializer_list<string>il):data(make_shared<vector<string>>(il)){} StrBlob(const StrBlob& sb):data(make_shared<vector<string>>(*sb.data)){} //13.26 StrBlob& operator=(const StrBlob& sb){ //13.26 data=make_shared<vector<string>>(*sb.data); //拷贝赋值函数不需要定义局部临时变量 shared_ptr特性 return *this; } size_type size()const{return data->size();} bool empty(){return data->empty();} void push_back(const string& str){data->push_back(str);} void pop_back(){ check(0,"pop_back on empty StrBlob"); data->pop_back(); } string& front()const { check(0,"front on empty StrBlob"); return data->front(); } string& back()const { check(0,"back on empty StrBlob"); return data->back(); }private: shared_ptr<vector<string>> data; void check(size_type i,const string& msg)const{ if(i>=data->size()) throw out_of_range(msg); }};int main(){// 13.24// HasPtr的成员ps指向的string的内存是动态分配的,如果用合成的析构函数,那么那段内存就不会被释放,造成内存泄露// 13.25// 我们想让StrBlob像一个值,那么每个StrBlob都应该有一块独立的内存,// 而合成版本的拷贝构造函数和拷贝赋值运算符不会分配内存,需要我们自己定义函数来分配内存// 又因为StrBlob的唯一成员是智能指针,当指针指向对象的use_count为1时自动销毁内存,所有不需要我们来手动销毁动态内存. return 0;}
13.27 13.28
#include<iostream>#include<vector>using namespace std;class HasPtr{ //13.27public: HasPtr():ps(new string()),use(new int(1)){} HasPtr(const string&s=string()):ps(new string(s)),i(0),use(new int(1)){} HasPtr(const HasPtr& hp):ps(hp.ps),i(hp.i),use(hp.use){ ++(*hp.use); } HasPtr& operator=(const HasPtr& hp){ ++(*(this->use)); --(*(this->use)); if(this->use==0){ delete (this->ps); delete (this->use); } this->ps=hp.ps; this->i=hp.i; this->use=hp.use; return *this; } ~HasPtr(){ --(*(this->use)); if(this->use==0){ delete (this->ps); delete (this->use); } }private: string *ps; int i; int* use;};class TreeNode{ //行为像指针 //13.28public: TreeNode():value(""),count(new int(1)),left(nullptr),right(nullptr){} //left,right指向的内存应该在其他函数内分配 TreeNode(const TreeNode& tr) :value(tr.value),count(tr.count),left(tr.left),right(tr.right){ ++(*tr.count); } TreeNode& operator=(const TreeNode& tr){ ++(*tr.count); --(*this->count); if(*(this->count)==0){ delete this->count; delete this->left; //可以delete空指针 delete this->right; } this->value=tr.value; this->count=tr.count; this->left=tr.left; this->right=tr.right; return *this; } ~TreeNode(){ --(*this->count); if(*(this->count)==0){ delete this->count; delete this->left; delete this->right; } }private: string value; int* count; TreeNode *left; TreeNode *right;};class BinStrTree{ //行为像值public: BinStrTree():root(new TreeNode()){} BinStrTree(const BinStrTree& bst):root(new TreeNode(*bst.root)){} BinStrTree& operator=(const BinStrTree& bst){ TreeNode* tr=new TreeNode(*bst.root); delete this->root; this->root=tr; return *this; } ~BinStrTree(){ delete this->root; }private: TreeNode *root;};int main(){ BinStrTree bst,bst2; bst2=bst; BinStrTree bst3=bst; return 0;}
11.29 11.30 11.31 11.32
#include<iostream>#include<string>#include<vector>#include<algorithm>using namespace std;class HasPtr{ friend void swap(HasPtr& lhs,HasPtr& rhs){// 11.29// 该swap内部调用的并不是自己,而是std::swap// 同时这些swap的参数类型也各不相同,证明不是递归调用自己 cout<<"call swap(HasPtr&,HasPtr&)"<<endl; std::swap(lhs.ps,rhs.ps); std::swap(lhs.i,rhs.i); } friend bool operator<(const HasPtr& lhs,const HasPtr& rhs){ return *lhs.ps<*rhs.ps; }public: HasPtr(const string&s=string()):ps(new string(s)),i(0){} HasPtr(const HasPtr& hp):ps(new string(*hp.ps)),i(hp.i){} HasPtr& operator=(const HasPtr& hp){ string* newp=new string(*hp.ps); delete this->ps; ps=newp; i=hp.i; return *this; } ~HasPtr(){delete ps;}//private: string *ps; int i;};int main(){// 11.30 HasPtr a("aaaaaaa"); HasPtr c("sssssss"); swap(a,c);// 11.31 vector<HasPtr>vec{c,a}; vec.push_back(HasPtr("gggggggggg")); vec.push_back(HasPtr("wwwwwwwwww")); vec.push_back(HasPtr("dddddddddd")); sort(vec.begin(),vec.end());// 11.32// 本质上值版本的swap就是为了避免临时的内存分配,从而提高性能// 而指针版本的类在赋值的过程中本来就不需要分配临时内存,所以指针版本不会得到益处. return 0;}
13.33-----13.38
//Folder_and_Message.h#include <string>#include <set>class Folder;//13.34class Message { friend class Folder;public: explicit Message(const std::string &str = ""):contents(str) { } Message(const Message&); Message& operator=(const Message&); ~Message(); void save(Folder&); void remove(Folder&);private: std::string contents; std::set<Folder*> folders; void add_to_Folders(const Message&); void remove_from_Folders();// 13.37 void addFldr(Folder *f) { folders.insert(f); } void remFldr(Folder *f) { folders.erase(f); }};// 13.36class Folder { friend class Message;public: Folder(){}; Folder(const Folder &); Folder& operator=(const Folder &); ~Folder();private: std::set<Message*> msgs; void add_to_Message(const Folder&); void remove_from_Message(); void addMsg(Message *m) { msgs.insert(m); } void remMsg(Message *m) { msgs.erase(m); }};
</pre><pre name="code" class="cpp">
//Folder_and_Message.cpp#include"Folder.h"using namespace std;Message::Message(const Message& msg):contents(msg.contents),folders(msg.folders){add_to_Folders(msg);}Message& Message::operator=(const Message& msg){ this->remove_from_Folders(); contents=msg.contents; folders=msg.folders; this->add_to_Folders(msg); return *this;}Message::~Message(){ remove_from_Folders();}void Message::save(Folder& f){ f.addMsg(this); folders.insert(&f);}// 13.33// 不用Folder:避免直接拷贝一个对象,提高性能// 不加const:在该函数中会对Folder的对象进行insert操作,需要改变它void Message::remove(Folder& f){ f.remMsg(this); folders.erase(&f);}void Message::add_to_Folders(const Message& msg){ for(auto f:msg.folders) f->addMsg(this);}void Message::remove_from_Folders(){ for(auto f:this->folders) f->remMsg(this);}//-------------------------------------------------Folder::Folder(const Folder& f):msgs(f.msgs){add_to_Message(f);}Folder& Folder::operator=(const Folder& f){ this->remove_from_Message(); msgs=f.msgs; this->add_to_Message(f); return *this;}Folder::~Folder(){remove_from_Message();}void Folder::add_to_Message(const Folder& f){ for(auto i:f.msgs) i->addFldr(this);}void Folder::remove_from_Message(){ for(auto i:this->msgs) i->remFldr(this);}// 13.35// 书中原话:当我们拷贝一个message时,得到的副本应该与原message出现在相同的Folder中// 对新拷贝的message对象,如果用的是默认合成拷贝构造函数// 则新的message不会添加进入那些包含原message的folder中// 13.38//@Mooophy: The copy and swap is an elegant way when working with dynamicly allocated memory. In the Message class ,// nothing is allocated dynamically. Thus using this idiom makes no sense and will make it more complicated to// implement due to the pointers that point back.//当涉及到动态分配内存时,拷贝并交换是一个完成该功能的精简的方式.//但是在Message类中,并未涉及到动态分配内存,这种方法并不会产生任何益处,//同时还会因为很多指针操作让程序变得更复杂难难以实现
13.39 13.40 13.41 13.43
//StrVec.h#include<iostream>#include<string>#include<vector>using namespace std;class StrVec{public: StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){} StrVec(initializer_list<string>); StrVec(const StrVec&); StrVec& operator=(const StrVec&); ~StrVec(){free();} void push_back(const string&); size_t size()const{return first_free-elements;} size_t capcity()const{return cap-elements;} string* begin()const{return elements;} string* end()const {return first_free;} void reserve(size_t); void resize(size_t,const string&); void resize(size_t);private: static allocator<string>alloc; void chk_n_alloc(){if(size()==capcity())reallocate();} pair<string*,string*> alloc_n_copy(const string*,const string*); void free(); void reallocate(); string *elements; string *first_free; string *cap;};
//StrVec.cpp#include"StrVec.h"#include<algorithm>allocator<string>StrVec::alloc;void StrVec::push_back(const string& s){ chk_n_alloc(); alloc.construct(first_free++,s); //13.41 //每次创造对象应该在first_free所指向的位置创造 //如果用前置递增则第一次push_back会浪费一个单位的内存没有被构造,同时first_free将指向容器内最后一个有对象的位置}pair<string*,string*> StrVec::alloc_n_copy(const string* bg,const string* ed){ auto data=alloc.allocate(ed-bg); return {data,uninitialized_copy(bg,ed,data)};}void StrVec::free(){ if(elements){ for(auto p=first_free;p!=elements;) alloc.destroy(--p); alloc.deallocate(elements,cap-elements); }}void free2(){ //13.43 此版本更好 不用考虑下标越界,更加简洁 for_each(elements,first_free,[](string& r){alloc.destroy(&r);});}StrVec::StrVec(const StrVec& s){ auto newdata=alloc_n_copy(s.begin(),s.end()); elements=newdata.first; first_free=cap=newdata.second;}StrVec& StrVec::operator=(const StrVec& s){ auto newdata=alloc_n_copy(s.begin(),s.end()); free(); elements=newdata.first; first_free=cap=newdata.second; return *this;}void StrVec::reallocate(){ auto newcapcity=size()?(size()*2):1; auto newdata=alloc.allocate(newcapcity); auto old_e=elements; auto dest=newdata; for(size_t i=0;i<size();++i) alloc.construct(dest++,std::move(*old_e++)); free(); elements=newdata; first_free=dest; cap=elements+newcapcity;}//13.39void StrVec::reserve(size_t n){ if(n>capcity()){ auto newcapcity=n; auto newdata=alloc.allocate(newcapcity); auto old_e=elements; auto dest=newdata; for(size_t i=0;i<size();++i) alloc.construct(dest++,std::move(*old_e++)); free(); elements=newdata; first_free=dest; cap=elements+newcapcity; }}void StrVec::resize(size_t n){ resize(n,string());}void StrVec::resize(size_t n,const string& str){ auto dest=elements+n; if(n<size()){ while(first_free!=dest) alloc.destroy(--first_free); } else{ if(n>capcity())reallocate(); while(first_free!=dest) alloc.construct(first_free++,str); }}StrVec::StrVec(initializer_list<string>lst){ //13.40 auto newdata=alloc_n_copy(lst.begin(),lst.end()); elements=newdata.first; first_free=cap=newdata.second;}
//main.cpp#include <iostream>#include<vector>#include"StrVec.h"using namespace std;int main(){// 13.39 StrVec sv({"aa","bbb","cccc","gggg"}); //13.40 sv.push_back("ssssssss"); sv.push_back("ddddd"); sv.push_back("eeeeee"); cout<<sv.size()<<" "<<sv.capcity()<<endl; sv.reserve(20); cout<<sv.size()<<" "<<sv.capcity()<<endl; sv.resize(12,"asd"); cout<<sv.size()<<" "<<sv.capcity()<<endl; sv.resize(10); cout<<sv.size()<<" "<<sv.capcity()<<endl; return 0;}
13.44
#include<iostream>#include<algorithm>#include<cstring>using namespace std;class ChVec{public: ChVec():elements(nullptr),cap(nullptr){} ChVec(const char* ch,size_t len); ChVec(const ChVec&); ChVec& operator=(const ChVec&); ~ChVec(){free();} size_t capacity(){return cap-elements;} void print(){for(char* p=elements;p<cap;p++)cout<<*p;cout<<endl;}private: allocator<char>alloc; char* elements; char* cap; void free(){ if(elements){ size_t len=cap-elements; while(cap!=elements) alloc.destroy(--cap); alloc.deallocate(elements,len); } } pair<char*,char*> alloc_n_copy(const char* st,const char* ed){ char* data=alloc.allocate(ed-st); return {data,uninitialized_copy(st,ed,data)}; }};ChVec::ChVec(const char* ch,size_t len){ auto newdata=alloc_n_copy(ch,ch+len); elements=newdata.first; cap=newdata.second;}ChVec::ChVec(const ChVec& cv){ auto newdata=alloc_n_copy(cv.elements,cv.cap); elements=newdata.first; cap=newdata.second;}ChVec& ChVec::operator=(const ChVec& cv){ auto newdata=alloc_n_copy(cv.elements,cv.cap); free(); elements=newdata.first; cap=newdata.second; return *this;}int main(){ ChVec cv1; cv1.print(); cout<<cv1.capacity()<<endl; char* str="aaaaaaaaaaaaaassdd"; ChVec cv(str,strlen(str)); cv.print(); cout<<cv1.capacity()<<endl; return 0;}
13.45 -----13.48
#include<iostream>#include<algorithm>#include<vector>#include<cstring>using namespace std;class String{public: String():elements(nullptr),cap(nullptr){} String(const char* ch,size_t len); String(const String&); String& operator=(const String&); ~String(){free();} size_t capacity(){return cap-elements;} void print(){for(char* p=elements;p<cap;p++)cout<<*p;cout<<endl;}private: allocator<char>alloc; char* elements; char* cap; void free(){ if(elements){ size_t len=cap-elements; while(cap!=elements) alloc.destroy(--cap); alloc.deallocate(elements,len); } } pair<char*,char*> alloc_n_copy(const char* st,const char* ed){ char* data=alloc.allocate(ed-st); return {data,uninitialized_copy(st,ed,data)}; }};String::String(const char* ch,size_t len){ auto newdata=alloc_n_copy(ch,ch+len); elements=newdata.first; cap=newdata.second;}String::String(const String& cv){ auto newdata=alloc_n_copy(cv.elements,cv.cap); elements=newdata.first; cap=newdata.second; cout<<"String(const String& cv)"<<endl; // 13.47}String& String::operator=(const String& cv){ auto newdata=alloc_n_copy(cv.elements,cv.cap); free(); elements=newdata.first; cap=newdata.second; cout<<"operator=(const String& cv)"<<endl; // 13.47 return *this;}int f(){return 1;}int main(){// 13.45// 左值引用:绑定左值(通常称为变量)// 右值引用:绑定右值(通常是字面常量或者即将销毁的变量)// 13.46 vector<int>vi(100); int&& r1=f(); //函数返回临时变量 int& r2=vi[0]; //vi[0]是一个变量 int& r3=r1; //r1是一个表达式(左值) int&& r4=vi[0]*f(); //乘积为临时变量// 13.48 vector<String>vec; char* s="aaaaa"; String str(s,strlen(s)); cout<<"------------"<<endl; vec.push_back(String("ssssss",7)); cout<<"------------"<<endl; vec.push_back(String("sssddd",7)); cout<<"------------"<<endl; vec.push_back(String("asd",3)); cout<<"------------"<<endl; vec.push_back(String("asdd",4)); return 0;}
13.49
//StrVecStrVec::StrVec( StrVec&& sv):elements(sv.elements),first_free(sv.first_free),cap(sv.cap){ sv.cap=sv.first_free=sv.elements=nullptr;}StrVec& StrVec::operator=(StrVec&& sv){ if(this!=&sv){free(); elements=sv.elements; first_free=sv.first_free; cap=sv.cap; sv.cap=sv.first_free=sv.elements=nullptr; } return *this;}//StringString::String(String&& st):elements(st.elements),cap(st.cap){ st.elements=st.cap=nullptr;}String& String::operator=(String&& st){ if(&st!=this){ free(); elements=st.elements; cap=st.cap; st.elements=st.cap=nullptr; } return *this;}//Messagevoid Message::move_folder(Message* msg){ folders=std::move(msg->folders); for(auto f:folders){ f->remMsg(msg); f->addMsg(this); } (msg->folders).clear();}Message::Message(Message&& msg):contents(std::move(msg.contents)){ move_folder(&msg);}Message& Message::operator=(Message&& msg){ if(this!=&msg){ remove_from_Folders(); contents=std::move(msg.contents); move_folder(&msg); } return *this;}
13.51----13.54
#include<iostream>#include<string>using namespace std;class HasPtr{ friend void swap(HasPtr& l,HasPtr& r){ std::swap(l.ps,r.ps); std::swap(l.i,r.i); }public: HasPtr(const string& s=string()):ps(new string(s)),i(0){cout<<"HasPtr(const string& s=string())"<<endl;} HasPtr(const HasPtr& p):ps(new string(*p.ps)),i(p.i){cout<<"HasPtr(const HasPtr& p)"<<endl;} ~HasPtr(){delete ps;cout<<"~HasPtr()"<<endl;} HasPtr(HasPtr &&p)noexcept : ps(p.ps),i(p.i){p.ps=0;cout<<"HasPtr(HasPtr &&p)"<<endl;} HasPtr& operator=(HasPtr rhs){ swap(*this,rhs); cout<<"HasPtr& operator=(HasPtr rhs)"<<endl; return *this; }// 13.53//HasPtr& operator=(HasPtr& rhs){// delete ps;// swap(*this,rhs);// cout<<"HasPtr& operator=(HasPtr& rhs)"<<endl;// return *this;// }// HasPtr& operator=(HasPtr&& rhs){// ps=std::move(rhs.ps);// i=std::move(rhs.i);// rhs.ps=nullptr;// cout<<"HasPtr& operator=(HasPtr&& rhs)"<<endl;// return *this;// }private: string* ps; int i;};int main(){// 13.51// 因为函数返回的是一个右值,是一个即将销毁的智能指针// 因为unique_ptr有一个移动构造函数:unique_ptr::unique_ptr(unique_ptr && src);// (参数为一个右值,也就是把函数返回的右值移动到新的unique_ptr上);// 13.52 HasPtr hp,hp2;// 调用两次构造函数 cout<<"--------------------"<<endl; hp=hp2;// 调用一次拷贝构造函数(复制给operator=的形参)// 调用一次operator=// 一次析构函数(销毁形参对象) cout<<"--------------------"<<endl; hp=std::move(hp2);// 调用一次移动构造函数// 一次operator= (形参通过移动构造函数得到)// 3次析构// 13.54// error: ambiguous overload for 'operator=' (operand types are 'HasPtr' and 'std::remove_reference<HasPtr&>::type { aka HasPtr }')// hp1 = std::move(*pH); return 0;}
13.55------13.58
#include<iostream>#include<string>#include<algorithm>#include<vector>using namespace std;// 13.58class Foo{public: Foo sorted()&&; Foo sorted()const & ;private: vector<int> data;};Foo Foo::sorted()&{ sort(data.begin(),data.end()); return *this;}// 13.57 函数内部调用&&版本 没有问题Foo Foo::sorted()const&{ return Foo(*this)sorted();};// 13.55void push_back(string&& s){ data->push_back(std::move(s));}// 13.56//ret是临时创建的变量(左值) ,所以调用sorted即是调用的自己,将会无限递归死循环
0 0
- c++primer(第五版) 第十三章 拷贝控制习题答案
- c++ primer(第五版)学习笔记及习题答案代码版(第十三章)拷贝控制
- C++primer第五版笔记-第十三章拷贝控制
- C++Primer第五版 第十三章习题答案(1~10)
- C++Primer第五版 第十三章习题答案(11~20)
- C++Primer第五版 第十三章习题答案(21~30)
- C++Primer第五版 第十三章习题答案(31~40)
- C++Primer第五版 第十三章习题答案(41~50)
- C++Primer第五版 第十三章习题答案(51~58)
- C++Primer(第五版) 习题答案
- C++Primer 中文版 第五版 第五章课后习题答案
- 《C++primer(第五版)》学习之路-第十三章:拷贝控制
- C++Primer 第五版 (课本习题答案)
- c++ primer(第五版)笔记 第十三章(1) 拷贝控制
- c++ primer(第五版)笔记 第十三章(2) 拷贝控制
- c++ primer(第五版)笔记 第十三章(3) 拷贝控制
- C++Primer 中文版 第五版 第二章课后习题答案
- C++Primer 中文版 第五版 第三章课后习题答案
- 浅谈Java中的equals和==
- 如何学好图像处理——从小白到大神?
- [leetcode 250]Count Univalue Subtrees ------元素都相同的子树个数
- 素数筛选法-Eratosthenes筛法优化
- 搜索区间
- c++primer(第五版) 第十三章 拷贝控制习题答案
- 使用基于ThinkPHP3.2.3的ThinkAdmin创建手机电脑通用的表白墙(八)移动端index
- poj 1769 Minimizing maximizer 线段树
- IOS:使用jenkins实现xcode自动打包
- Activity的四种启动模式和onNewIntent()
- Java NIO和IO的区别
- laravel 学习笔记一 (异常处理)
- 在android中如何使用全局变量
- nyoj 2括号匹配 栈入门