首页 > 代码库 > 《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章 动态内存 读书笔记 习题答案