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可以进行拷贝赋值无需转让所有权这一举

 

 

 


 

posted @ 2022-08-05 21:44  yddl  阅读(66)  评论(0编辑  收藏  举报