码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2014-09-09 21:28:39      阅读:413      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   color   os   io   使用   ar   for   

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

 

在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章 动态内存 读书笔记 习题答案

标签:des   style   blog   color   os   io   使用   ar   for   

原文地址:http://www.cnblogs.com/kkkwjx/p/3947380.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!