c++Primer第十二章:动态内存

智能指针

shared_ptr

允许多个指针指向同一对象
自动完成销毁工作,自动释放关联内存

一般操作

与new无关的初始化

shared_ptr<T> p(q);
shared_ptr<string> p = make_shared<string>(10,'9');
auto p = make_shared<T>(q);//q可以为空 ()

检查是否为空

if(p&&p->empty())

shared_ptr 与unique_ptr都支持的操作

项目Value
shared_ptr< T > sp
unique_ptr< T > up
p作为判断条件
*p获取其对象
p.get()返回p中保存的指针
p.swap(q)
swap(p,q)

shared_ptr独有的操作

项目Value
p=qp指向q,q的引用计数+1
p.unique()p.use_count()=1t rue
p.use_count()

内存释放过程

shared_ptr<f> factory(T arg){
	return make_shared<f>(arg);
}
void use_factory(T arg){
	auto p = factory(arg);
	//p使用过程,一旦离开了作用域指向的内存会自动释放
}

//但是use_factory如果是这种就不会
shared_ptr<f> use_factory(T arg){
	auto p = factory(arg);
	return p;
}

代码测试

	shared_ptr<int> w(new int(100));
	cout<<w.use_count()<<endl;
	auto w1 = w;
	int * p = w.get();
	cout<<"w.use_count()="<<w.use_count()<<endl;
	cout<<"w1.use_count()="<<w1.use_count()<<endl;
	w1 = nullptr;
	cout<<"w.use_count()="<<w.use_count()<<endl;
	cout<<"w1.use_count()="<<w1.use_count()<<endl;
	cout<<"p="<<*p<<endl;
	w = nullptr;
	cout<<"p="<<*p<<endl;
	w.reset(new int (1024));
	cout<<"w="<<*(w.get())<<endl;

结果
在这里插入图片描述

shared_ptr与new与list

常见定义和修改shared_ptr的其他方法

不要用get进行赋值

auto temp = shared_ptr<int>(new int(p))
//管理q所指对象,q必须指向new分配的内存,且能转换为T*类型
shared_ptr<T> p(q);
//接管unique_ptr 并将其置空
shared_ptr<T> p(u);
//接管q,q能转换为T*类型,p使用d来代替delete
shared_ptr<T> p(q,d);
//p是p2拷贝,唯一的区别是后面
shared_ptr<T> p(p2,d);
//若p是唯一指向该对象的智能指针,则会释放此对象
p.reset();
//若p是唯一指向该对象的智能指针,则会释放此对象,p指向q
p.reset(q);
//同时调用d来释放q
p.reset(q,d);

例如,删除时自动调用del
如果智能指针管理的资源不是new分配的内存,记得传递一个删除器,尤其是管理链接资源的时候

bool del(int *p){
    delete [] p;
}

shared_ptr<int> shared(new int[100],del);//使用函数

shared_ptr<int> ptr(new int[100],
[](int *p){delete [] p;});//使用lambda表达式


保留list,删空间

	list<int*> l1;
	int n=10;
	while(n--){
		int *p = new int(n);
		l1.push_back(p);
	}
	cout<<"list:"<<endl;
	for(auto e: l1){
		cout<<*e<<" ";
	}
	cout<<endl;
	int *temp = (int*)*(l1.begin());
	cout<<"temp="<<*temp<<endl;
	for(auto e= l1.begin();e!=l1.end();){
		int *p=(int*)*e;
		//e = l1.erase(e);
		cout<<*(*e)<<endl;
		e++;
		delete p;
	}
	for(auto e: l1){
		cout<<*e<<" ";
	}
	cout<<l1.size()<<endl;
	cout<<"temp="<<*temp<<endl;
	cout<<endl;

结果:内存中的值都已经释放了
在这里插入图片描述
list与空间全删

list<int*> l1;
	int n=10;
	while(n--){
		int *p = new int(n);
		l1.push_back(p);
	}
	cout<<"list:"<<endl;
	for(auto e: l1){
		cout<<*e<<" ";
	}
	cout<<endl;
	int *temp = (int*)*(l1.begin());
	cout<<"temp="<<*temp<<endl;
	for(auto e= l1.begin();e!=l1.end();){
		int *p=(int*)*e;
		//if()
			delete p;
			e = l1.erase(e);
		//else e++;
	}
	cout<<"again:"<<endl;
	for(auto e: l1){
		cout<<*e<<" ";
	}
	cout<<endl;
	cout<<"size="<<l1.size()<<endl;
	cout<<"temp="<<*temp<<endl;
	cout<<endl;
	return 0;	 

结果
在这里插入图片描述
list 智能指针释放空间

	list<shared_ptr<int>> sp;
	int n=10;
	while(n--){
		shared_ptr<int> temp(new int (n));
		sp.push_back(temp);
	}
	for(auto e:sp){
		cout<<*e<<" ";
	}
	cout<<endl;
	auto temp = sp.begin();
	cout<<*(*temp)<<endl;
	sp.erase(sp.begin());
	cout<<*(*temp)<<endl;

结果,erase之后 自动释放空间了,比直接delet方便
在这里插入图片描述

unique_ptr

常用操作

unique_ptr<T> u1
unique_ptr<T> u2
unique_ptr<T,D> u(d)
u = nullptr
//放弃控制权
u.release()
//释放对象
u.reset()
u.reset(q)
u.reset(nulptr)

weak_ptr

不增加计数值

weak_ptr<T> w
weak_ptr<T> w(sp)
//p可以是weak_ptr,shared_ptr
w=p
w.reset()
w.use_count()
//use_count = 0 ture
w.expired()
//expired = 0 返回空shared_ptr否则返回一个指向w的对象shared_ptr
w.lock()

代码测试

StrBlobPtr.h

#ifndef STRBLOBPTR
#define STRBLOBPTR
#include<iostream>
#include<memory>
#include<vector>
#include<string>
#include"StrBlob.h"
using namespace std;
class StrBlob;
class StrBlobPtr
{
private:
    //若检查成功返回一个指向vector的shared_ptr
    shared_ptr<vector<string>> check(size_t,const string &)const;
    //指向一个vector<string>的weak_ptr
    weak_ptr<vector<string>> wptr;
    //在数组中的当前位置
    size_t curr;
public:
    StrBlobPtr():curr(0){};
    StrBlobPtr(StrBlob &b,size_t sz=0):wptr(b.data),curr(sz){};
    int wptr_use_count(){return wptr.use_count();};
    string &deref() const;
    //前缀递增
    StrBlobPtr& incr();
};
#endif

StrBlobPtr.cpp

#include"StrBlobPtr.h"
//弱指针可以返回共享指针
shared_ptr<vector<string>> StrBlobPtr::check(size_t i,const string &msg)const{
    //vector是否还存在
    auto ret = wptr.lock();
    if(!ret)
        throw runtime_error("unbound StrBlobPtr");
    if(i>ret->size())
        throw out_of_range(msg);
    return ret;
}

string &StrBlobPtr::deref() const{
    auto p = check(curr,"dereference past end");
    //对象所指的Vector
    return (*p)[curr];
}

StrBlobPtr &StrBlobPtr::incr(){
    check(curr,"increment past end of StrBlobPtr");
    ++curr;
    return *this;
}

StrBlob.cpp

#include"StrBlob.h"
#include"StrBlobPtr.h"
void StrBlob::check (size_type i ,const string &t)const{
    if(i>=data->size())
        throw out_of_range(t);
}
string& StrBlob::front(){
    check(0,"front on empty StrBlob");
    return data->front();
}

string & StrBlob::back(){
    check(0,"back on empty StrBlob");
    return data->back();
}
void StrBlob::pop_back(){
    check(0,"pop_back on empty StrBlob");
    data->pop_back();
}
//StrBlobPtr(StrBlob &b,size_t sz=0)
StrBlobPtr StrBlob::begin(){
    return StrBlobPtr(*this);
}
//StrBlobPtr(StrBlob &b,size_t sz=0){..cur(sz)}
StrBlobPtr StrBlob::end(){
        auto ret = StrBlobPtr(*this,data->size()-1);return ret;
}

StrBlob.h

//shared_ptr 使用
#ifndef STRBLOB
#define STRBLOB
#include<iostream>
#include<string>
#include<memory>
#include<vector>
using namespace std;
typedef vector<string>::size_type size_type;
class StrBlobPtr;
class StrBlob
{
private:
    //共享的数据
    shared_ptr<vector<string>> data;
    //抛出异常
    void check(size_type i,const string &t) const;
public:
    friend class StrBlobPtr;
    //默认构造分配一个空vector
    StrBlob():data(make_shared<vector<string>>()){}
    //make_shared :返回一个shared_ptr 以il初始化vector<string>对象
    StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(il)){};
    int data_use_count(){return data.use_count();}
    
    
    
    //返回对象的长度
    
    
    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();

    //出现error: invalid use of incomplete type 'class StrBlob'
    StrBlobPtr begin(); //{return StrBlobPtr(*this);}
    StrBlobPtr end(); //{auto ret = StrBlobPtr(*this,data->size());return ret;}
};
#endif


main.cpp

    StrBlob b2;
    StrBlob b1 = {"a","an","the"};
    cout<<"use_count="<<b1.data_use_count()<<endl;
    b2 = b1;
    cout<<"use_count="<<b1.data_use_count()<<endl;
    b2.push_back("about");
    cout<<"b1.size = "<<b1.size()<<endl;
    cout<<"b2.size = "<<b2.size()<<endl;
    cout<<"b1.front = "<<b1.front()<<endl;
    cout<<"b2.front = "<<b2.front()<<endl;
    cout<<"b1.begin().def()="<<b1.begin().deref()<<endl;
    cout<<"b2.begin().def()="<<b2.begin().incr().deref()<<endl;
    cout<<"b1.end().def()="<<b1.end().deref()<<endl;
    StrBlobPtr b3(b1);
    b3.incr();
    b3.incr();
    //b3内部是弱指针 所以不会添加use_count;
    cout<<"b3.deref()="<<b3.deref()<<endl;
    cout<<"b2.begin().def()="<<b2.begin().incr().deref()<<endl;
    cout<<"b3.deref()="<<b3.deref()<<endl;
    cout<<"use_count="<<b1.data_use_count()<<endl;
    cout<<"use_count="<<b3.wptr_use_count()<<endl;

结果
在这里插入图片描述

new delet

delete p;
delete [] pa;

unique_ptr 自动调用删除器进行数组管理

unique_ptr<int[]> up(new int[10]);
up.release();

shared_ptr必须自己提供删除器

shared_ptr<int> sp(new int[10],[](int *p){delete[] p;});
sp.reset();

allocator

p427写不动了······感觉用的也少

文本查询代码

TextQuery.cpp

#include"TextQuery.h"

//make_plural(wc, "word ", "s ")当输入中文本中,word数大于一是在word后加s,为words为word的复数!
string make_plural(size_t ctr,const string &word, const string &ending)
{
  return (ctr==1) ? word : word+ending;                                           
}
ostream &print(ostream &os,const QueryResult &qr){
    os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(),"times","s")<<endl;
    for(auto num: *qr.lines){
        os<<"\t(line "<<num+1<<")"<<*(qr.file->begin() + num)<<endl;
    }
    return os;
    
}


//share指针只能直接初始化,所以再函数后面接着
TextQuery::TextQuery(ifstream & is):file(new vector<string>)
{
    string text;
    //逐行读取
    while(getline(is,text)){
        //保存每一行
        file->push_back(text);
        //行号
        int n = file->size()-1;
        istringstream line(text);
        string word;
        //分解每一行的单词
        while(line>>word){
            //不在就加入,在则插行号  或者可以使用引用
            //auto &line = wm[word];
            if(!wm[word])
                //分配一个新set
                wm[word].reset(new set<line_no>);
            wm[word]->insert(n);
            
        }

    }
}

TextQuery::~TextQuery()
{
    cout<<"TextQuery End"<<endl;
}

QueryResult TextQuery::query(const string &sought) const{
    //如果没有找到就返回一个指向此set的指针 没懂为什么是静态的
    static shared_ptr<set<line_no>> nodata(new set<line_no>);
    //查找到的单词所对应的set
    auto loc = wm.find(sought);
    if(loc == wm.end())
        return QueryResult(sought,nodata,file);
    else
        return QueryResult(sought,loc->second,file); 
}

void runQueries(ifstream &infile){
    TextQuery tq(infile);
    while ((true))
    {
        cout<<"endter word to look for,or q toquit: "<<endl;
        string s;
        //cout<<"cin s"<<endl;
        cin>>s;
        //cout<<"cout s"<<endl;
        if(s == "q"){
            break;
        }
        //cout<<"print s"<<endl;
        print(cout,tq.query(s))<<endl;
    }
    
}

TextQuery.h

#ifndef TEXTQUERY
#define TEXTQUERY
#include<iostream>
#include<string>
#include<vector>
#include<memory>
#include<fstream>
#include<map>
#include<set>
#include<sstream>
using namespace std;
typedef vector<string>::size_type line_no;   
//对结果的总结
class QueryResult{
public:
    //打印
    friend ostream &print(ostream &,const QueryResult&);
    //对结果进行整合
    QueryResult(string s,shared_ptr<set<line_no>> p,shared_ptr<vector<string>> f):sought(s),lines(p),file(f){};
private:
    //查询的单词
    string sought;
    //出现的行号
    shared_ptr<set<line_no>> lines;
    //输入的文件
    shared_ptr<vector<string>> file;
};

class TextQuery
{
private:
    //输入文件
    shared_ptr<vector<string>> file;
    //每个单词到它所在行号的集合的映射
    map<string,shared_ptr<set<line_no>>> wm;
public:
    //要查询的是文件
    TextQuery(ifstream &);
    //查询函数
    QueryResult query(const string &) const;
    ~TextQuery();
};
//次数>1  time要加s 
string make_plural(size_t ctr,const string &word, const string &ending);
//要查询的文件
void runQueries(ifstream &infile);
#endif

main.cpp

 ifstream fs("E:\\code\\word.txt");
 runQueries(fs);

结果
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值