1.智能指针也是模板,定义方式一样
2.make_shared<>最安全的分配和调用方法
auto p=make_shared<vector<string>>();//指向一个动态分配的空vector
3.引用计数
auto r=make_shared<int>(42);
r=q;//递增q指向的对象的引用计数;递减r指向的引用计数
4.StrBlob类
#ifndef STRBLOB_H
#define STRBLOB_H
#include
#include
#include
#include
#include
using namespace std;
class StrBlobPtr;
class StrBlob
{
friend class StrBlobPtr;
friend bool operator==(const StrBlob&, const StrBlob&);
public:
typedef vector<string>::size_type size_type;
StrBlob();
StrBlob(initializer_list<string> il);
StrBlob(vector<string> *p) :data(p){}
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();
const string& front() const;
string& back();
const string& back() const;
string& operator[](size_t i){ return data[i]; }
/*StrBlobPtr begin();
StrBlobPtr end();*/
~StrBlob();
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string& msg) const;
};
#endif
#include "StrBlob.h"
StrBlob::StrBlob() :data(make_shared<vector<string>>()){}
StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)){}
void StrBlob::check(size_type i, const string &msg) const
{
if (i >= data->size())
throw out_of_range(msg);
}
string& StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
const string& StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
string& StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const string& StrBlob::back() const
{
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::begin()
//{
// return StrBlobPtr(*this);
//}
//StrBlobPtr StrBlob::end()
//{
// auto ret= StrBlobPtr(*this,data->size());
// return ret;
//}
StrBlob::~StrBlob()
{
}
1.使用new动态分配和初始化对象
int *p1=new int;//p指向未初始化int对象
int *p2=new int(2);//指,向2
string *s=new string(9,'9');//指向"9999999999"
vector<int> *pv=new vector<int>{1,2,3};
2.使用auto,只有括号仅有单一初始化器才能使用
auto p=new auto(obj);//p指向obj类型
auto p=new auto{a,b,c};//错误
3.动态分配const
const int *pci=new const int(1024);
const string *psc=new const string;
4.内存耗尽
int *p2=new (nothrow) int;//如果分配失败,new返回空指针,bad_alloc和nothrow都定义在new头文件中
5.指针值和delete
6.使用new和delete三个常见问题
7.习题
vector<int>* f1()
{
return new vector<int>;
}
shared_ptr<vector<int>> f11()
{
return make_shared<vector<int>>();
}
void f2()
{
vector<int> *pv = f1();
int a;
while (cin >> a)
{
pv->push_back(a);
}
f3(pv);
delete pv;
}
void f21()
{
auto p = f11();
int a;
while (cin >> a)
{
p->push_back(a);
}
}
void f3(vector<int> *pv)
{
for (const auto &e : *pv)
cout << e;
}
void f31(shared_ptr<vector<int>> p)
{
for (const auto &a : *p)
cout << a;
}
1.
shared_ptr<int> p1=new int(1024);//错误
shared_ptr<int> p2(new int(1024));//正确:使用了直接初始化
2.普通指针与智能指针混淆
3.不用使用get初始化另一个智能指针
shared_ptr<int> p(new int(42));
int *q=p.get();//OK
4.reset操作
防止智能指针陷阱规范
shared_ptr<connection> p(&c,end_connection);
1.使用unique_ptr必须采用直接初始化形式
2.不能拷贝或赋值unique_ptr,但可以调用release和reset转移
unique_ptr<string> p2(p1.release());//将所有权权从p1转移给p2
unique_ptr<string> p3(new string("Telsa"));
p2.reset(p3.release);//将所有权从p3转移到p2
3.传递unique_ptr参数和返回unique_ptr
//虽然不能拷贝,但是对于即将销毁的unique_ptr可以
unique_ptr<int> clone(int p)
{
return unique_ptr<int>(new int(p));
}
4.向unique_ptr传递删除器
//重载删除器时,需要在尖括号内指定删除器类型
unique_ptrdecltype(end_connection)*> p(&c,end_connection);
1.使用shared_ptr初始化,但不会改变引用计数
auto p=make_shared<int>(42);
weak_ptr<int> wp(wp);
2.使用lock返回shared_ptr
shared_ptr<int> np=wp.lock();
3.StrBlobPtr类
#pragma once
#include"StrBlob.h"
class StrBlobPtr
{
friend bool eq(const StrBlobPtr&, const StrBlobPtr&);
public:
StrBlobPtr() :curr(0){}
StrBlobPtr(StrBlob &a, size_t sz = 0):wptr(a.data), curr(sz){}
string& deref()const;
StrBlobPtr& incr();
StrBlobPtr& decr();
~StrBlobPtr();
string& operator[](size_t t){ return (*wptr.lock())[t]; }
private:
shared_ptr<vector<string>> check(size_t, const string&)const;
weak_ptr<vector<string>> wptr;
size_t curr;
};
class IsmorethanN{
public:
IsmorethanN(size_t n) :sz(n){}
bool operator()(const string &s){ return s.size >= sz; }
private:
size_t sz;
};
int main()
{
string s = "sdfsdfsd";
if (IsmorethanN(5)(s))
cout << "yes" << endl;
int sz=5;
auto f = [sz](const string &s){return s.size() >= sz; };
}
#include "StrBlobPtr.h"
shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg)const
{
auto ret = wptr.lock();
if (!ret)
throw runtime_error("unbound strblobptr");
if (i >= ret->size())
throw out_of_range(msg);
}
string& StrBlobPtr::deref()const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
StrBlobPtr& StrBlobPtr::incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr& StrBlobPtr::decr()
{
--curr;
check(-1, "decrement past begin of StrBlobPtr");
return *this;
}
inline bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
if (l == r)
return (!r || lhs.curr == rhs.curr);
else
return false;
}
StrBlobPtr::~StrBlobPtr()
{
}
1.动态数组并不是数组类型,返回的是元素指针
int *pia=new int[10];//10个未初始化的int
string *s=new string[10]();//10个空string
string *sa=new string[2](){"11","22"};
2.动态分配为0
char arr[0];//错误
char *arr=new char[0];//正确
3.delete
delete[] pa;//按逆序销毁元素
4.unique_ptr管理动态数组
unique_ptr<int[]> up(new int[10]);
up.release();//delete[]
5.使用shared _ptr必须自己定义删除器
shared_ptr<int> sp(new int[10],[](int *p){delete[] p;});
sp.reset();//会使用自定义delete]
1.在memory头文件中,是一个模板
allocator<string> alloc;
auto const p=alloc.allocate(n);
2.allocator分配为构造的内存
auto q=p;
alloc.construct(q++);
alloc.construct(q++,10,'c');
alloc.construct(q++,"hi");
3.拷贝和填充未初始化内存的算法
auto p=alloc.allocate(vi.size()*2);
auto q=uninitialized_copy(vi.begin(),vi.end(),p);//通过拷贝vi中的元素来构造从p开始的元素
uninitialized_fill_n(q,vi.size(),42);//剩余初始化为42
TextQuery.h
#pragma once
#include
#include"QueryResult.h"
#include
#include
#include
//class QueryResult;
class TextQuery
{
public:
using line_no = vector<string>::size_type;
TextQuery(ifstream&);
QueryResult query(const string&);
void display_map();
TextQuery();
~TextQuery();
private:
StrBlob file;
map<string, shared_ptr<set >> wm;
string cleamup_str(const string&);
};
TextQuery.h
#pragma once
#include
#include"QueryResult.h"
#include
#include
#include
//class QueryResult;
class TextQuery
{
public:
using line_no = vector<string>::size_type;
TextQuery(ifstream&);
QueryResult query(const string&);
void display_map();
TextQuery();
~TextQuery();
private:
StrBlob file;
map<string, shared_ptr<set >> wm;
string cleamup_str(const string&);
};
TextQuery.cpp
#include "TextQuery.h"
using namespace std;
TextQuery::TextQuery()
{
}
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){
word = cleamup_str(word);
auto &lines = wm[word];
if (!lines)
lines.reset(new set );
lines->insert(n);
}
}
}
string TextQuery::cleamup_str(const string& word)
{
string ret;
for (auto it = word.begin(); it != word.end();++it)
if (!ispunct(*it))
ret += tolower(*it);
return ret;
}
QueryResult TextQuery::query(const string& sought)
{
static shared_ptr<set > nodata(new set );
auto loc = wm.find(cleamup_str(sought));
if (loc == wm.end())
return QueryResult(sought, nodata, file);
else
return QueryResult(sought, loc->second, file);
}
void TextQuery::display_map()
{
auto iter = wm.cbegin(), iter_end = wm.cend();
for (; iter != iter_end; ++iter){
cout << "word: " << iter->first << " {";
auto text_locs = iter->second;
auto loc_iter = text_locs->cbegin();
auto loc_iter_end = text_locs->cend();
while (loc_iter != loc_iter_end)
{
cout << *loc_iter;
if (++loc_iter != loc_iter_end)
cout << ",";
}
cout << "}\n";
}
cout << endl;
}
TextQuery::~TextQuery()
{
}