美文网首页
c++primer 12.10-12.22

c++primer 12.10-12.22

作者: 青吟乐 | 来源:发表于2019-05-28 12:03 被阅读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;
    }
    
    
    

    相关文章

      网友评论

          本文标题:c++primer 12.10-12.22

          本文链接:https://www.haomeiwen.com/subject/nmvrtctx.html