c++primer 12.10-12.22

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;
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容