C++primer练习12.1-12.18
练习12.1
在此代码的结尾,b1和b2各包含多少个元素?
strblob b1;
{strblob b2={“a”,“an”,“the”};
b1=b2;
b2.push_back(“about”);}
::各包含4个
练习12.2
编写你自己的strblob类,包含const版本的front和back
class StrBlob{ public: typedef vector<string>::size_type size_type; StrBlob(); StrBlob(initializer_list<string> il); size_type size()const{return data->size();} bool empty()const{return data->empty();} void push_back(const string &t){data->push_back(t);} void pop_back(); string &front(); string &back(); string &front()const; string &back()const; private: shared_ptr<vector<string>> data; void check(size_type i,const string &msg)const; }; void StrBlob::check(size_type i,const string &msg)const { if(i>=data->size()) throw out_of_range(msg); } string &StrBlob::front() { check(0,"empty StrBlob"); return data->front(); } string &StrBlob::back() { check(0,"empty StrBlob"); return data->back(); } string &StrBlob::front()const { check(0,"empty StrBlob"); return data->front(); } string &StrBlob::back()const { check(0,"empty StrBlob"); return data->back(); } void StrBlob::pop_back() { check(0, "pop_back on empty StrBlob"); data->pop_back(); }
练习12.3
StrBlob需要const版本的push_back和pop_back吗?
:: 需要,这两个操作,都涉及到对成员变量的修改操作。为了保证共享对象的元素不会在这个操作中修改状态,需要加上const。
练习12.4
在我们的check函数中,没有检查i是否大于0.为什么可以忽略这个检查?
::size_type大于等于0
练习12.5
我们未编写接受一个initializer_list explicit参数的构造函数。讨论这个设计策略的优缺点
::暂时只能用明确形容优点,不灵活概况缺点
练习12.6
编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数,这个函数读取标准输入,将读入的值保存在vector元素中,再将vector传递给另一个函数,打印读入的值。
记得在恰当的时候delete vector
vector<int>* func() { auto p=new vector<int>; int tem; cin>>tem; p->push_back(tem); return p; } void use_func() { auto p=func(); cout<<*p->begin()<<endl;
delete p; } int main() { use_func(); }
练习12.7
重做上一题,这次使用shared_ptr而不是内置指针
shared_ptr<vector<int>> func() { auto p=make_shared<vector<int>>(); int tem; cin>>tem; p->push_back(tem); return p; } void use_func() { auto p=func(); cout<<*p->begin()<<endl; } int main() { use_func(); }
练习12.8
下面的函数是否有错误?如果有,解释错误原因
bool b(){
int *p=new int;
//...
return p;}
::无法释放内置指针,传出去的是bool值,在之后的程序无法再使用该指针
练习12.9
解释下面代码的执行结果
int* q=new int (42),*r=new int(100);
r=q;
auto q2=make_shared<int>(42),r2=make_shared<int>(100);
r2=q2;
::内置指针都指向值为42的对象,且100的对象未被释放,将一直存在,智能指针100的对象被清除,俩指针指向42
练习12.10
下面的代码调用了第413页中定义的process函数,解释此调用是否正确,如果不正确,应如何修改
shared_ptr<int>p(new int(42));
process(shared_ptr<int>(p));
::正确,先是显式初始化shared_ptr,接着拷贝给process的形参,此时计数为2,函数结束,销毁形参指针,计数回到1,只有p一个shared_ptr指向对象
练习12.11
如果我们像下面这样调用process会发生什么
process(shared_ptr<int>(p.get()));
::当函数结束时会delete指向对象,让p变成空悬指针,使用p会有危险
练习12.12
p和q的定义如下,对于接下来的对process的每个调用,如果合法,解释它做了什么,如果不合法,解释错误原因
auto p =new int();
auto sp = make_shared<int>();
(a) process(sp);
(
b)process(new int());
(c)process(p);
(d)process(shared_ptr<int>(p));
::(a)传入shared_ptr,正常调用,计数加一,结束减1
(b)传入错误,不可将内置指针拷贝给shared_ptr
(c)同b
(d)同a,将内置指针显式初始化成shared_ptr(临时构造指针)
练习12.13
如果执行下面的代码,会发生什么
auto sp=make_shared<int>();
auto p=sp.get();
delete p;
::使sp空悬,使用有风险
练习12.14
编写你自己版本的用shared_ptr管理connection的函数
struct destination; struct connection; connection connect(destination); void disconnect(connection); void end(connection*p){disconnect(*p);} void f(destination &d) { connection c=connect(d); shared_ptr<connection> p=(&c,end); }
练习12.15
重写程序,用lambda代替end_connection函数
struct destination; struct connection; connection connect(destination); void disconnect(connection); void f(destination &d) { connection c=connect(d); shared_ptr<connection> p=(&c,[](connection *p){disconnect(*p);}); }
练习12.16
如果你试图拷贝或赋值unique_ptr,编译器并不总是能给出易于理解的错误信息。编写包含这种错误的程序,观察编译器如何诊断这种错误
{ unique_ptr<int> p; auto p1=p; }
[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>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
练习12.17
下面的unique_ptr声明中,哪些是合法的,哪些可能导致后续的程序错误?解释每个错误的问题出在哪
int ix = 1024, * pi = &ix, * pi2 = new int(2048);
typedef unique_ptr<int> IntP;
(a)IntP p0(ix);错误,定义一个unique_ptr时需要指针初始化,无法将int转换成指针
(b)IntP p1(pi);合法,但p1被销毁时,pi是未定义的
(c)IntP p2(pi2);合法,用一个指向动态内存的指针初始化是正确的
(d)IntP p3(&ix);合法,同(b)
(e)IntP p4(new int(2048));合法,同(c)
(f)IntP p5 (p2.get());合法,但是p5被销毁时,p2可能成为空悬指针,这点有待质疑,试了还是没有被影响,如果谁能解答下疑惑就好,看网上都说普通指针赋给unique_ptr会随之销毁,搞不懂
练习12.18
shared_ptr为什么没有release成员?
::shared_ptr可以进行拷贝赋值无需转让所有权这一举
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具