首页 > 代码库 > 《C++primer》v5 第12章 动态内存 读书笔记 习题答案

《C++primer》v5 第12章 动态内存 读书笔记 习题答案

这一章暂时没写完,先留着以后再写。

 

在C++程序中,程序员可以给手动开辟内存,但是这块内存需要手动释放,不便管理,因此新标准提供智能指针类型来管理动态对象。它负责自动释放所指向的对象。

shared_prt允许多个指针指向同一个对象

unique_ptr独占所指向的对象

weak_ptr是一个弱引用,指向shared_ptr所管理的对象

一些操作:

p=q;//递减p的引用计数,递增q的引用计数

shared_ptr<T> p(q);//p是q的拷贝,递增q的引用计数

通过make_shared<T>(args)来返回一个shared_ptr。

每个shared_ptr都有一个关联的计数器,称其为引用计数。无论何时拷贝shared_ptr都会递增此计数器,当shared_ptr被赋予新值或shared_ptr被销毁则计数器就会递减。

12.1

#include<memory>using namespace std;class StrBlob{public:    typedef std::vector<std::string>::size_type size_type;    StrBlob();    StrBlob(std::initializer_list<std::string> il);    size_type size() const    {        return data->size();    }    bool empty()const    {        return data->empty();    }    void push_back(const std::string &t)    {        data->push_back(t);    }    void pop_back();    std::string& front();    std::string& back();private:    std::shared_ptr<std::vector<std::string>> data;    void check(size_type i,const std::string &msg) const;};StrBlob::StrBlob():data(make_shared<vector<string>>()) {};StrBlob::StrBlob(std::initializer_list<std::string> il):data(make_shared<vector<string>>(il)) {};void StrBlob::check(size_type i,const string &msg) const{    if(i>=data->size())        throw out_of_range(msg);}string& StrBlob::front(){    check(0,"front on empty StrBlob");    return data->front();}string& StrBlob::back(){    check(data->size()-1,"back on empty StrBlob");    return data->back();}void StrBlob::pop_back(){    check(data->size()-1,"back on empty StrBlob");    return data->pop_back();}int main(){    StrBlob b1;    {        StrBlob b2={"a","an","the"};        b1=b2;        b2.push_back("about");    }    cout<<b1.size()<<endl;    return 0;}

b1内有4个,b2已被销毁

12.2

#include<memory>using namespace std;class StrBlob{public:    typedef std::vector<std::string>::size_type size_type;    StrBlob();    StrBlob(std::initializer_list<std::string> il);    size_type size() const    {        return data->size();    }    bool empty()const    {        return data->empty();    }    void push_back(const std::string &t)    {        data->push_back(t);    }    void pop_back();    std::string& front();    std::string& back();    std::string& front()const;    std::string& back()const;private:    std::shared_ptr<std::vector<std::string>> data;    void check(size_type i,const std::string &msg) const;};StrBlob::StrBlob():data(make_shared<vector<string>>()) {};StrBlob::StrBlob(std::initializer_list<std::string> il):data(make_shared<vector<string>>(il)) {};void StrBlob::check(size_type i,const string &msg) const{    if(i>=data->size())        throw out_of_range(msg);}string& StrBlob::front(){    check(0,"front on empty StrBlob");    return data->front();}string& StrBlob::back(){    check(data->size()-1,"back on empty StrBlob");    return data->back();}string& StrBlob::front() const{    check(0,"front on empty StrBlob");    return data->front();}string& StrBlob::back() const{    check(data->size()-1,"back on empty StrBlob");    return data->back();}void StrBlob::pop_back(){    check(data->size()-1,"back on empty StrBlob");    return data->pop_back();}

12.3

不需要。

常量的智能指针没有意义?

12.4

data->size()一定是大于等于0的

12.5

由于没用explicit使得我们可以StrBlob b2={"a","an","the"};这样来初始化一个b2.

12.6

vector<int>* build(){    return new vector<int>;}void read(vector<int>* p, istream &in){    int a;    while(in>>a)        p->push_back(a);}void out(const vector<int>*p, const ostream &in){    for(auto i:*p)        cout<<i<<endl;}void dead(vector<int> *p){    delete p;    p=nullptr;}int main(){    auto *p=build();    read(p,cin);    out(p,cout);    dead(p);    return 0;}

12.7

shared_ptr<vector<int>> build(){    return make_shared<vector<int>>();}void read(shared_ptr<vector<int>> p, istream &in){    int a;    while(in>>a)        p->push_back(a);}void out(const shared_ptr<vector<int>> p, const ostream &in){    for(auto i:*p)        cout<<i<<endl;}int main(){    auto p=build();    read(p,cin);    out(p,cout);    return 0;}

12.8

返回值是bool类型,却返回一个int指针,而且最后没有释放p指向的内存。

12.9

开辟一个int空间初始化为42并用q指向它,开辟一个int空间初始化为100并用r指向它

令r指向指针p指向的内存空间,r原来指向的内存忘记释放。

开辟内存空间初始化并用智能指针指向它

令r2指向q2指向的内存空间,r2原来的内存空间自动释放。

12.10

不要混用普通指针和智能指针。智能指针引用计数为0时将释放内存,如果用普通指针所指内存初始化智能指针,可能使得智能指针释放该内存,而导致原普通指针成为空悬指针。

正确?

12.11

将导致p指向的内存被释放

12.12

(a)合法,不会导致内存释放

(b)不合法,不能用普通指针隐式转化成智能指针

(c)不合法,同上

(d)合法,将导致内存释放

12.13

delete了get()得到的指针,在智能指针引用计数为0时将再次释放该内存。将导致该内存被释放两次。

12.14

使用删除器。在析构前调用该函数。

using namespace std;struct destinaiton {};struct connection {};connection connect(destinaiton *d){}void end_connection(connection *p){    cout<<"close connection!"<<endl;}void f(destinaiton &d){    connection c=connect(&d);    shared_ptr<connection> p(&c,end_connection);}int main(){    destinaiton d;    f(d);    return 0;}

12.15

using namespace std;struct destinaiton {};struct connection {};connection connect(destinaiton *d){}void f(destinaiton &d){    connection c=connect(&d);    shared_ptr<connection> p(&c,[](const connection *const p){cout<<"close connection!"<<endl;});}int main(){    destinaiton d;    f(d);    return 0;}

12.16

某个时刻只能有一个unique_ptr指向给定的对象,它不能用make_shared返回一个unique_ptr,只能将其绑定到一个new返回的指针上,必须采用直接初始化,不支持普通的拷贝或赋值。

u.release()//u放弃对指针的控制权,并返回它,将u置空

u.reset()\u=nullptr//释放u指向的对象

u.reset(p)//如果提供了内置指针则则令u指向这个对象,否则将u置空

C:\Users\Administrator\Desktop\C++_code\a.cpp|35|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

(a)错误。用整型去初始化智能指针。

(b)错误。用智能指针去指向一个非动态变量。

(c)正确。

(d)错误,同b

(e)正确。

(f)正确,但是可能导致释放内存,使得p2出错。

12.18

对对象有控制权的有多个智能指针,转移控制权可以通过拷贝或赋值,无须release。

12.19

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<stdexcept>#include<memory>using namespace std;class StrBlobPtr;class StrBlob{    friend class StrBlobPtr;public:    StrBlobPtr begin();    StrBlobPtr end();    typedef std::vector<std::string>::size_type size_type;    StrBlob();    StrBlob(std::initializer_list<std::string> il);    size_type size() const    {        return data->size();    }    bool empty()const    {        return data->empty();    }    void push_back(const std::string &t)    {        data->push_back(t);    }    void pop_back();    std::string& front();    std::string& back();    std::string& front()const;    std::string& back()const;private:    std::shared_ptr<std::vector<std::string>> data;    void check(size_type i,const std::string &msg) const;};StrBlob::StrBlob():data(make_shared<vector<string>>()) {};StrBlob::StrBlob(std::initializer_list<std::string> il):data(make_shared<vector<string>>(il)) {};void StrBlob::check(size_type i,const string &msg) const{    if(i>=data->size())        throw out_of_range(msg);}string& StrBlob::front(){    check(0,"front on empty StrBlob");    return data->front();}string& StrBlob::back(){    check(data->size()-1,"back on empty StrBlob");    return data->back();}string& StrBlob::front() const{    check(0,"front on empty StrBlob");    return data->front();}string& StrBlob::back() const{    check(data->size()-1,"back on empty StrBlob");    return data->back();}void StrBlob::pop_back(){    check(data->size()-1,"back on empty StrBlob");    return data->pop_back();}class StrBlobPtr{public:    StrBlobPtr():curr(0) {}    StrBlobPtr(StrBlob &a,size_t sz=0):wptr(a.data),curr(sz) {}    std::string &deref()const;    StrBlobPtr &incr();private:    std::shared_ptr<std::vector<std::string>> check(std::size_t ,const std::string &) const;    std::weak_ptr <std::vector<std::string>> wptr;    std::size_t curr;};std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i,const std::string &msg) const{    auto ret=wptr.lock();    if(!ret)        throw std::runtime_error("unbound StrBlobPtr");    if(i>=ret->size())        throw std::out_of_range(msg);    return ret;}std::string& StrBlobPtr::deref()const{    auto p=check(curr,"dereference past end");    return (*p)[curr];}StrBlobPtr &StrBlobPtr::incr(){    check(curr,"increment past end of StrBlobPtr");    ++curr;    return *this;}StrBlobPtr StrBlob::begin(){    return StrBlobPtr(*this);}StrBlobPtr StrBlob::end(){    auto ret=StrBlobPtr(*this,data->size());    return ret;}

 

12.20\21\22

暂略吧,没看懂这一块。

12.23

int main(){    char *s=new char [100];    strcpy(s,"abc");    strcat(s,"xxxx");    cout<<s<<endl;    delete[] s;    return 0;}
int main(){    string a,b;    cin>>a>>b;    cout<<a+b<<endl;    return 0;}

d

12.24

 暂时没想到。。

12.25

delete []pa;

12.26

 

《C++primer》v5 第12章 动态内存 读书笔记 习题答案