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