c++primer 12.10-12.22

2019-05-28  本文已影响0人  青吟乐

12.10
1,初始化p,此时p的引用为1;
2,process值用p去初始化另一个临时智能指针,p的引用值为2,另一个临时的智能指针引用为1
3,process结束后临时智能指针销毁,p的引用为1;
程序正常运行

12.11
首先get函数时得到智能指针的内置指针 所以,process内得到的是p的内置指针

我不明白为什么大家都说会内存空间会销毁,并且指针悬空,我决定去问问。。
这个题目最终应该是在process方法内内存会被释放掉,会产生空悬指针的问题,但是我还想不太明白根本原因所以以后完善

第一次完善:智能指针是局部变量,它被销毁时候指向的地址顺带也被销毁,所以产生了悬空指针的问题

12.12
1,合法,智能指针参数
2,不合法参数不允许默认转换
3,不合法,参数不允许默认转换
4,合法,并且process完成后内存空间被释放,要注意p指针悬空的问题

12.13
delete释放掉sp和p指向的内存,
因为sp的引用还是1,所以sp还未失效,但是它指向的那块内存已经被释放了,所以后续再对sp进行操作会出现错误;

12.14

#include <iostream>
#include<memory>
using namespace std;

//connection 是连接需要的信息
struct connection
{
    //连接ip与端口号
    string ip;
    int port;
    connection(string i, int p) : ip(i), port(p) {}
};
//destination 表示连接的目的地
 struct destination
{
    //连接目标的ip与端口号
    string ip;
    int port;
    destination(string i, int p) : ip(i), port(p) {}
 };


 connection connect(destination* pd)
 {
    //智能指针:指向一个connection对象
    shared_ptr<connection> pc(new connection(pd->ip, pd->port));
    //显示创建连接的信息
    cout << "创建连接(" << pc.use_count() << ")" << std::endl;
    return *pc;
 }


void disconnect(connection pc)
 {
    //显示关闭廉价而的信息
    std::cout << "关闭连接(" << pc.ip << ":" << pc.port << ")" << std::endl;
 }


 //关闭连接的方法
 void end_connection(connection* pc)
 {
    //调用关闭连接
    disconnect(*pc);
 }

//
 void f(destination &d)
 {
    //创建连接对象
    connection conn = connect(&d);
    //智能指针:指向连接实体
    shared_ptr<connection> p(&conn, end_connection);
    //显示正在连接
    cout << "正在连接(" << p.use_count() << ")" << endl;
 }



int main()
{
    destination dest("111.111.11111.111", 10086);//目的连接信息
    f(dest);

    return 0;
}

12.15
shared_ptr中的第二个参数写lamda表达式

#include <iostream>
#include<memory>
#include <string>
using namespace std;

class destination{
public:
    std::string ip;
    int port;
    destination(string i,int p):ip(i),port(p){}
};
class connection{
public:
    std::string ip;
    int port;
    connection(string i,int p):ip(i),port(p){}
};


connection connect(destination* pDest)
 {
    std::shared_ptr<connection> pConn(new connection(pDest->ip, pDest->port));
    std::cout << "创建连接(" << pConn.use_count() << ")" << std::endl;
    return *pConn;
}

void disconnection(connection pc){
    std::cout<<"关闭连接("<<pc.ip<<":"<<pc.port<<")"<<std::endl;
}
void f(destination &d){
    connection conn = connect(&d);
    std::shared_ptr<connection> p(&conn,[](connection* pc){ disconnection(*pc);});
    cout<<"正在连接("<<p.use_count()<<")"<<endl;
}
int main()
{
    destination d("1111.11.11",1024);
    f(d);
    return 0;
}

12.16

 use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = std::basic_string<char>; _Dp = std::default_delete<std::basic_string<char> >]'|

使用了已经被删除的函数,这种使用已经不被支持了,也就是已经不支持拷贝的操作了

12.17
(a)不合法,必须使用new也就是动态内存初始化unique_ptr
(b)合法,但是有有可能在后续程序中p1销毁时释放指向的内存空间,使pi悬空出现问题
(c)也有可能使得pi2成为悬空指针
(d)不合法,编译没有问题,但是因为p3有可能会被销毁,但是此时指向的内存是栈中的内存,不能释放栈中内存
(e)正常
(f) 不合法,指针悬空

12.18
因为share_ptr不是独享型,不需要在释放该指针与内存的链接的时候进行重新赋值,在释放之前就可以先做好释放的准备工作
12.19
相对于书上,真正值得注意的点是需要对!运算符进行重载,在for循环的时候用得到


#include <string>
#include <vector>
#include <initializer_list>
#include <stdexcept>
#include <memory>

class StrBlobPtr;
class StrBlob;
class StrBlob {
public:
    friend class StrBlobPtr;
    //返回指向首元素和尾后元素的StrBoloPtr
    StrBlobPtr begin();
    StrBlobPtr  end();

    //将std::vector<std::string>::size_type重命名为size_type
    typedef std::vector<std::string>::size_type size_type;
    StrBlob():data(std::make_shared<std::vector<std::string>>()){}
    StrBlob(std::initializer_list<std::string> il): data(std::make_shared<std::vector<std::string>>(il)){}

    //size是返回智能指针指向的vector的长度
    size_type size() const {
        return data->size();
    }
    //判断智能指针指向的vector是否为空
    bool empty() const{
        return data->empty();
    }
    //添加和删除元素
    void push_back(const std::string &t){
        data->push_back(t);
    }
    void pop_back(){
        check(0,"pop_back on empty StrBlob");
        data->pop_back();
    }

    //元素访问
    std::string& front() const{
        //若vector为空,check抛出异常
        check(0,"front on empty StrBlob");
        return data->front();
    }

    std::string& back() const{
        check(0,"back on empty StrBlob");
        return data->back();
    }
    std::string& front()
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }

    std::string& back()
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }


private:

    //data是一个指向vector<string> 的智能指针
    std::shared_ptr<std::vector<std::string>> data;

    //check是用来检查越界的方法
    void check(size_type i, const std::string &msg) const{
        if(i>=data->size()){
            throw std::out_of_range(msg);
        }
    }
};
class StrBlobPtr{
public:
    StrBlobPtr():curr(0){}
    StrBlobPtr(StrBlob &a,std::size_t sz = 0):wptr(a.data),curr(sz){}
    //返回当前指向的vertor的第curr个元素
    std::string& deref(){
        auto p = check(curr,"dereference past end");
        return (*p)[curr];
    }

    //重载!运算符,使其对StrBlobPtr对象的curr对象进行判断
    bool operator!=(const StrBlobPtr& p) { return p.curr != curr; }

    //前缀递增:返回递增后的对象的引用
    StrBlobPtr& incr(){
        //如果curr已经指向容器的为尾后位置,就不能递增
        check(curr,"incerement past of StrBlolPte");
        ++curr;
        return *this;
    }

private:
    //同样有个检查方法,检查指针指向的vector是否还存在,存在则返回该智能指针
    std::shared_ptr<std::vector<std::string>> check(std::size_t i, const std::string & msg) const{
        auto ret = wptr.lock();//vector是否还有关联
        if(!ret){
            throw std::runtime_error("unbound StrBlobPtr");
        }
        if(i>=ret->size()){
            throw std::out_of_range(msg);
        }
        return ret;
    }
    //保存一个weak_ptr,意味着底层的vector可能会被销毁
    std::weak_ptr<std::vector<std::string>> wptr;
    //保存数组当前的位置
    std::size_t curr;
};

StrBlobPtr StrBlob::begin()
{
    return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
    return StrBlobPtr(*this, data->size());
}


#endif

12.20

#include <iostream>
#include<fstream>
#include<vector>
#include"class.h"
using namespace std;



int main()
{
    //文件读入流
    ifstream ifs("C:\\study\\c++test\\endless.txt");

    string str;
    StrBlob sb;

    while(ifs>>str){
        sb.push_back(str);
    }
    for(StrBlobPtr sbt = sb.begin();sbt!= sb.end();sbt.incr()){
        cout<<sbt.deref()<<endl;
    }

    return 0;
}

12.21
内容上都一样
但是书上的版本比较好理解,可读性更高
12.22
相对于20题的版本,加两个const版本的cbegin和cend函数
将ConstStrBlobPtr的构造函数的

StrBlob &a

改成

const StrBlob &a

就使得ConstStrBlobPtr指向了一个const StrBlob
下面是完整的代码

#include<iostream>
#include<fstream>
#include<sstream>
#include <string>
#include <vector>
#include <initializer_list>
#include <stdexcept>
#include <memory>

class ConstStrBlobPtr;
class StrBlob;
class StrBlob {
public:
    friend class ConstStrBlobPtr;
    //返回指向首元素和尾后元素的StrBoloPtr
    ConstStrBlobPtr begin();
    ConstStrBlobPtr  end();

    ConstStrBlobPtr cbegin() const;
    ConstStrBlobPtr cend() const;

    //将std::vector<std::string>::size_type重命名为size_type
    typedef std::vector<std::string>::size_type size_type;
    StrBlob():data(std::make_shared<std::vector<std::string>>()){}
    StrBlob(std::initializer_list<std::string> il): data(std::make_shared<std::vector<std::string>>(il)){}



    //size是返回智能指针指向的vector的长度
    size_type size() const {
        return data->size();
    }
    //判断智能指针指向的vector是否为空
    bool empty() const{
        return data->empty();
    }
    //添加和删除元素
    void push_back(const std::string &t){
        data->push_back(t);
    }
    void pop_back(){
        check(0,"pop_back on empty StrBlob");
        data->pop_back();
    }

    //元素访问
    std::string& front() const{
        //若vector为空,check抛出异常
        check(0,"front on empty StrBlob");
        return data->front();
    }

    std::string& back() const{
        check(0,"back on empty StrBlob");
        return data->back();
    }
    std::string& front()
    {
        check(0, "front on empty StrBlob");
        return data->front();
    }

    std::string& back()
    {
        check(0, "back on empty StrBlob");
        return data->back();
    }


private:


    //data是一个指向vector<string> 的智能指针
    std::shared_ptr<std::vector<std::string>> data;

    //check是用来检查越界的方法
    void check(size_type i, const std::string &msg) const{
        if(i>=data->size()){
            throw std::out_of_range(msg);
        }
    }
};
class ConstStrBlobPtr{
public:
    ConstStrBlobPtr():curr(0){}
    ConstStrBlobPtr(const StrBlob &a,std::size_t sz = 0):wptr(a.data),curr(sz){}
    //返回当前指向的vertor的第curr个元素
    std::string& deref(){
        auto p = check(curr,"dereference past end");
        return (*p)[curr];
    }

    bool operator!=(const ConstStrBlobPtr& p) { return p.curr != curr; }

    //前缀递增:返回递增后的对象的引用
    ConstStrBlobPtr& incr(){
        //如果curr已经指向容器的为尾后位置,就不能递增
        check(curr,"incerement past of StrBlolPte");
        ++curr;
        return *this;
    }

private:
    //同样有个检查方法,检查指针指向的vector是否还存在,存在则返回该智能指针
    std::shared_ptr<std::vector<std::string>> check(std::size_t i, const std::string & msg) const{
        auto ret = wptr.lock();//vector是否还有关联
        if(!ret){
            throw std::runtime_error("unbound StrBlobPtr");
        }
        if(i>=ret->size()){
            throw std::out_of_range(msg);
        }
        return ret;
    }
    //保存一个weak_ptr,意味着底层的vector可能会被销毁
    std::weak_ptr<std::vector<std::string>> wptr;
    //保存数组当前的位置
    std::size_t curr;
};

ConstStrBlobPtr StrBlob::begin()
{
    return ConstStrBlobPtr(*this);
}
ConstStrBlobPtr StrBlob::end()
{
    return ConstStrBlobPtr(*this, data->size());
}
ConstStrBlobPtr StrBlob::cbegin() const
{
    return ConstStrBlobPtr(*this);
}
ConstStrBlobPtr StrBlob::cend() const
{
    return ConstStrBlobPtr(*this, data->size());
}


int main()
{
    //文件读入流
    std::ifstream ifs("C:\\study\\c++test\\endless.txt");

    std::string str;
    StrBlob sb;

    while(getline(ifs,str)){
        sb.push_back(str);
    }
    for(ConstStrBlobPtr sbt = sb.begin();sbt!= sb.end();sbt.incr()){
        std::cout<<sbt.deref()<<std::endl;
    }
    for(ConstStrBlobPtr sbt = sb.cbegin();sbt!= sb.cend();sbt.incr()){
        std::cout<<sbt.deref()<<std::endl;
    }

    return 0;
}


上一篇下一篇

猜你喜欢

热点阅读