c++primer(第五版) 第十二章 动态内存习题答案

纯原创    转载请注明出处:http://blog.csdn.net/axuan_k



12.1  12.2  12.3  12.4  12.5

#include<iostream>
#include<vector>
#include<memory>
#include<string>
#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)){}

    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()
{
//  12.1
    StrBlob b1;    //b1 包含0个元素
    {
        StrBlob b2={"a","an","the"};   //b2包含3个元素
        b1=b2;                          //b1,b2包含同一个地址的4个元素
        b2.push_back("about");          //b1,b4包含同一个地址的4个元素
    }                                   //b2销毁,b1包含4个元素


//  12.2
    StrBlob sb;
    sb.push_back("ssss");
    sb.push_back("ssss2");
    sb.push_back("ssss3");
    sb.push_back("ssss4");
    cout<<sb.back()<<" "<<sb.front();
    sb.pop_back();
    cout<<"\n"<<sb.back()<<endl;
    cout<<sb.empty()<<endl;


//    12.3
//    You can certainly do this if you want to, but there doesn't seem to be any logical reason.
//    The compiler doesn't complain because this doesn't modify data (which is a pointer)
//    but rather the thing data points to, which is perfectly legal to do with a const pointer.
//                                                            ------by David Schwartz.
//    如果你想你可以加上const,但这并没有什么卵用,编译器并不会理会它因为无论有没有const也不会修改这个指针成员


//    12.4
//    我们定义的i是size_type类型,该类型没有符号,即使传入的参数是一个负数,也会被被强行修改(理解)为正数.
    
    
//    12.5
//    优点:编译器不会用这个构造函数来隐式转换,创建对象的时候我们能更清楚的知道自己使用的是哪一个构造函数.
//    缺点:让我们创建临时对象变得复杂.
    return 0;
}



12.6   12,7  12.8  12.9

#include<iostream>
#include<string>
#include<vector>
#include<memory>
using namespace std;
vector<int>* func(){
    return new vector<int>();
}
vector<int>* func2(vector<int>* p,istream& is){
    int a;
    while(is>>a)
        p->push_back(a);
    return p;
}
void print(vector<int>* p){
    for(int i:*p)
        cout<<i<<" ";
    cout<<endl;
    delete p;
}


shared_ptr<vector<int>> shared_func(){
    return make_shared<vector<int>>();
}

void shared_func2(shared_ptr<vector<int>>p,istream& is){
    int a;
    while(is>>a)
        p->push_back(a);
}
void shared_print(shared_ptr<vector<int>>p){
    for(int i:*p)
        cout<<i<<" ";
    cout<<endl;
}
int main(){
//    12.6
    vector<int>* vecp=func();
    vecp=func2(vecp,cin);
    print(vecp);


//    12.7
    shared_ptr<vector<int>> sp=shared_func();
    shared_func2(sp,cin);
    shared_print(sp);


//    12.8
//    当函数返回时, int*类型要转换为bool类型,而在返回前为指针分配的内容并没有释放
//    函数返回后,将不再有机会释放那一段内存


//    12.9
    int *q=new int(42), *r=new int(100);
    r=q;  //将r保存的地址赋值给q;q,r都指向int(42);(r原来保存的内容无法释放)
    auto q2=make_shared<int>(42), r2=make_shared<int>(100);
    r2=q2; //将q2保存的地址赋值给r2,r2原分配的内存没有智能指针指向它,被自动释放

    return 0;
}



12.10    12.11  12.12   12.13

#include <iostream>
#include<vector>
#include <string>
#include<memory>
using namespace std;
void process(shared_ptr<int> q){
    cout<<q.use_count()<<endl;
}
int main()
{
//    12.10
    shared_ptr<int> p(new int(42));
    cout<<p.use_count()<<endl;
    process(shared_ptr<int>(p));
    cout<<p.use_count()<<endl<<endl<<endl<<endl;
    //正确, 创建临时智能指针作为参数时 use_count+1,调用过后指针销毁-1
    //但自始至终p指向内存的use_count没有少于1,所以正确


//    12.11
    process(shared_ptr<int>(p.get()));
//  p会被销毁两次如P414解释的那样....(然而我的编译器并没有出现问题....)


//        12.12
    auto p2=new int();
    auto sp=make_shared<int>();
    process(sp);
    process(new int()); //错误,不能用构造函数隐式转换
    process(p2);        //错误,不能用构造函数隐式转换
    process(shared_ptr<int>(p2));
    
    
//    12.13
//    会出现销毁两次内存(delete一次,智能指针自动销毁一次)
    return 0;
}



 12.14    12.15

#include<iostream>
#include<string>
#include<memory>
using namespace std;
struct destination{
    string ip;
    int port;
    destination(string i,int p):ip(i),port(p){}
};
struct connection{
    string ip;
    int port;
    connection(string i,int p):ip(i),port(p){}
};

connection connect(destination* d){
    shared_ptr<connection>sp(new connection(d->ip,d->port));
    cout<<"Start create connection to "<<d->ip<<":"<<d->port<<endl;
    return *sp;
}

void disconnect(connection c){
    cout<<"You have disconnected to "<<c.ip<<":"<<c.port<<endl;
}

void end_connection(connection* cp){
    disconnect(*cp);
}

void f(destination& d){
    connection c=connect(&d);
//    shared_ptr<connection>sp2(&c,end_connection);
    //12.15
    shared_ptr<connection>sp2(&c,[](connection* cp){disconnect(*cp);});
    cout<<"You have connected to "<<d.ip<<":"<<d.port<<endl;
}
int main(){
    //12.14
    destination d("192.168.1.5",3430);
    f(d);
    return 0;
}



12.16    12.17   12.18

#include<iostream>
#include<string>
#include<memory>
using namespace std;
int main(){
//    12.16
    unique_ptr<int>a(new int(5));
//    unique_ptr<int>c(a);
//    unique_ptr<int>d=a;
//     拷贝 赋值 是同样的错误error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&)
//    [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp> = std::unique_ptr<int>]'|


//    12.17
    int ix=1024,*pi=&ix,*pi2=new int(2048);
    typedef unique_ptr<int> IntP;
    IntP p0(ix);  //编译错误 类型不匹配
    IntP p1(pi);    //p1离开它的范围会自动调用delete 而pi并不是堆(new)上分配的内存.
    IntP p2(pi2);   //p2离开范围区自动销毁 ,让pi2变成了悬空指针
    IntP p3(&ix);   //同p1(pi)
    IntP p4(new int(2048));
    IntP p5(p2.get());  // 分配的内存会被释放两次


//    12.18
//    shared_ptr可以直接拷贝复制给其他同类型智能指针,同时每个智能指针都能释放指向的对象
//      而unique则不行

    return 0;
}




12.19  12.20  12.21  12.22

#include<iostream>
#include<vector>
#include<memory>
#include<string>
#include<stdexcept>
#include<fstream>
using namespace std;
// 12 19
class StrBlobPtr;
class StrBlob{
    friend class StrBlobPtr;
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)){}

    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();
    }
    StrBlobPtr begin();
    StrBlobPtr end();
private:
    shared_ptr<vector<string>>data;
    void check(size_type i,const string& msg)const{
        if(i>=data->size())
            throw out_of_range(msg);
    }
};
class StrBlobPtr{
public:
    StrBlobPtr():curr(0){}
    StrBlobPtr(StrBlob& sb,size_t sz=0):wptr(sb.data),curr(sz){}
    string& deref()const{
        auto ret=check(curr,"dereference past end");
        return (*ret)[curr];
    }
    StrBlobPtr& incr(){
        check(curr,"increment past end of StrBlobPtr");
        curr++;
        return *this;
    }
private:
    weak_ptr<vector<string>>wptr;
    size_t curr;
    shared_ptr<vector<string>> check(size_t i,const string& msg)const{
        auto ret=wptr.lock();
        if(!ret)
            throw runtime_error(msg);
        if(i>ret->size())
            throw out_of_range(msg);
        return ret;
    }
};
StrBlobPtr StrBlob::begin(){return StrBlobPtr(*this);}
StrBlobPtr StrBlob::end(){return StrBlobPtr(*this,this->size());}
int main(){

//    12.20
    ifstream ifs("in.txt");
    string str;
    StrBlob sb;
    while(getline(ifs,str))
        sb.push_back(str);
    StrBlobPtr st(sb.begin());
    int length=sb.size();
    while(length--){
        cout<<st.deref()<<endl;
        st.incr();
    }


//  12.21
//    std::string& deref()const{return (*check(curr,"dereference past end"))[curr];}
//    此版本效率上没有发生变化,减少了中间变量的申明,虽然代码空间变少,但可读性降低了,不易理解


//    12.22
//    需要给48行StrBlobPtr的构造函数参数加上const
//    需要给36 37行的操作加上const(书中调用这两个操作构造StrBlobPtr)
//    StrBlobPtr(const StrBlob& sb,size_t sz=0):wptr(sb.data),curr(sz){}

    return 0;
}



12.26

#include<iostream>
#include<string>
#include<memory>
using namespace std;
int main(){
//    12.26
    const int n=25;
    allocator<string>all;
    string* p=all.allocate(n);
    string s;
    string *q=p;
    while(cin>>s&&q!=p+n){
            all.construct(q++,s);
    }
    size_t sz=q-p;
    while(q!=p){
        cout<<*--q<<endl;
        all.destroy(q);
    }
    all.deallocate(p,sz);
    return 0;
}




12.28    12.29

#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<fstream>
#include<sstream>
using namespace std;

int main(){
    //12.28
    map<string,set<int>>mp;
    vector<string>vec;
    ifstream ifs("in.txt");
    string temp,str;
    int num=0;
    while(getline(ifs,temp)){
        ++num;
        vec.push_back(temp);
        istringstream is(temp);
        while(is>>str)
            mp[str].insert(num);
    }
    while(1){
        cout<<"please input a word :"<<endl;
        cin>>str;
        auto ret=mp.find(str);
        if(ret==mp.end()){
            cout<<"Not have this word"<<endl;
            continue;
        }
        else{
            cout<<"occurs:"<<ret->second.size()<<endl;
            for(int i:ret->second)
                cout<<i<<" ";
            cout<<endl;
        }
    }


    12.29
    //此题两种类型的while效果一样,一般很少有人使用do while
    return 0;
}




12.30   12.31

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<fstream>
#include<memory>
using namespace std;
class QueryReasult{
    friend void print(ostream&,const QueryReasult&);
public:
    QueryReasult(string str,shared_ptr<set<int>>p,shared_ptr<vector<string>>p2)
    :sought(str),lines(p),file(p2){};
    set<int>::iterator begin()const{
private:
    string sought;
    shared_ptr<set<int>>lines;
    shared_ptr<vector<string>>file;
};

class TextQuery{
public:
    TextQuery(ifstream& ifs):file(new vector<string>){
        string line,str;
        int num=0;
        while(getline(ifs,line)){
            ++num;
            file->push_back(line);
//            cout<<111<<endl;
            istringstream is(line);
            while(is>>str){
                shared_ptr<set<int>>& ret=wm[str];
                if(!ret)
                    ret.reset(new set<int>);
                ret->insert(num);
            }
        }
    }
    QueryReasult query(const string& str)const{
        static shared_ptr<set<int>> nodata(new set<int>);
        auto ret=wm.find(str);
        if(ret==wm.end())
            return QueryReasult(str,nodata,file);
        return QueryReasult(str,ret->second,file);

    }
private:
    shared_ptr<vector<string>>file;
    map<string, shared_ptr<set<int>> >wm;
};
void print(ostream& os,const QueryReasult& qr){
    os<<qr.sought<<"  occurs "<<qr.lines->size()<<endl;
    for(auto i:*qr.lines)
        cout<<"line"<<i<<": "<<(*qr.file)[i-1]<<endl;;
    cout<<endl;
}
int main(){
//    12.30
    ifstream infile("in.txt");
    TextQuery tq(infile);
    string str;
    while(1){
        cout<<"please input a word:"<<endl;
        cin>>str;
        print(cout,tq.query(str));
    }

//    12.31
//    保存的下标会有重复 set更好,更简洁,不需要多余的代码和时间用来判断
    return 0;
}




12.32   12.33

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<fstream>
#include<memory>
#include<stdexcept>
using namespace std;
class QueryReasult;
class StrBlob{
     friend void print(ostream&,const QueryReasult&);
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)){}
    const string& get_string(int i){              //实在不会输出了 只好添加一个public函数
        return (*data)[i];
    }
    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);
    }
};
class QueryReasult{
    friend void print(ostream&,const QueryReasult&);
public:
    QueryReasult(string str,shared_ptr<set<int>>p,shared_ptr<StrBlob>p2)        //修改构造函数
    :sought(str),lines(p),file(p2){};
    set<int>::iterator begin()const{           //12.33
        return lines->begin();
    }
    set<int>::iterator end()const{              //12.33
        return lines->end();
    }
    shared_ptr<StrBlob> get_file()const{        //12.33
        return file;
    }
private:
    string sought;
    shared_ptr<set<int>>lines;
    shared_ptr<StrBlob>file;                    //修改成员
};

class TextQuery{
public:
    TextQuery(ifstream& ifs):file(new StrBlob){     //修改构造函数
        string line,str;
        int num=0;
        while(getline(ifs,line)){
            ++num;
            file->push_back(line);
            istringstream is(line);
            while(is>>str){
                shared_ptr<set<int>>& ret=wm[str];
                if(!ret)
                    ret.reset(new set<int>);
                ret->insert(num);
            }
        }
    }
    QueryReasult query(const string& str)const{
        static shared_ptr<set<int>> nodata(new set<int>);
        auto ret=wm.find(str);
        if(ret==wm.end())
            return QueryReasult(str,nodata,file);
        return QueryReasult(str,ret->second,file);

    }
private:
    shared_ptr<StrBlob> file;                         //修改成员
    map<string, shared_ptr<set<int>> >wm;
};
void print(ostream& os,const QueryReasult& qr){
    os<<qr.sought<<"  occurs "<<qr.lines->size()<<endl;
    for(auto i:*qr.lines)
        cout<<"line"<<i<<": "<<qr.file->get_string(i-1)<<endl;     //调用get_string
    cout<<endl;
}
int main(){
//    12.32
    ifstream infile("in.txt");
    TextQuery tq(infile);
    string str;
    while(1){
        cout<<"please input a word:"<<endl;
        cin>>str;
        print(cout,tq.query(str));
    }

    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值