纯原创 转载请注明出处: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.4 Point 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.5 private: 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.11 private: 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.18 public: 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 constructor TextQuery::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.27 public: 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.28 public: 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.34 class 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.36 class 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.39 void 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
//StrVec StrVec::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; } //String String::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; } //Message void 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.58 class 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.55 void push_back(string&& s){ data->push_back(std::move(s)); } // 13.56 //ret是临时创建的变量(左值) ,所以调用sorted即是调用的自己,将会无限递归死循环
时间: 2024-10-07 18:35:58