目录
智能指针
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=q | p指向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);
结果