纯原创 转载请注明出处:http://blog.csdn.net/axuan_k
12.1 12.2 12.3 12.4 12.5
#include<iostream>
#include<vector>
#include<memory>
#include<string>
#include<stdexcept>
using namespace std;
class StrBlob
{
public:
typedef vector<string>::size_type size_type;
StrBlob():data(make_shared<vector<string>>()){}
StrBlob(initializer_list<string>il):data(make_shared<vector<string>>(il)){}
size_type size()const{return data->size();}
bool empty(){return data->empty();}
void push_back(const string& str){data->push_back(str);}
void pop_back(){
check(0,"pop_back on empty StrBlob");
data->pop_back();
}
string& front()const
{
check(0,"front on empty StrBlob");
return data->front();
}
string& back()const
{
check(0,"back on empty StrBlob");
return data->back();
}
private:
shared_ptr<vector<string>>data;
void check(size_type i,const string& msg)const{
if(i>=data->size())
throw out_of_range(msg);
}
};
int main()
{
// 12.1
StrBlob b1; //b1 包含0个元素
{
StrBlob b2={"a","an","the"}; //b2包含3个元素
b1=b2; //b1,b2包含同一个地址的4个元素
b2.push_back("about"); //b1,b4包含同一个地址的4个元素
} //b2销毁,b1包含4个元素
// 12.2
StrBlob sb;
sb.push_back("ssss");
sb.push_back("ssss2");
sb.push_back("ssss3");
sb.push_back("ssss4");
cout<<sb.back()<<" "<<sb.front();
sb.pop_back();
cout<<"\n"<<sb.back()<<endl;
cout<<sb.empty()<<endl;
// 12.3
// You can certainly do this if you want to, but there doesn't seem to be any logical reason.
// The compiler doesn't complain because this doesn't modify data (which is a pointer)
// but rather the thing data points to, which is perfectly legal to do with a const pointer.
// ------by David Schwartz.
// 如果你想你可以加上const,但这并没有什么卵用,编译器并不会理会它因为无论有没有const也不会修改这个指针成员
// 12.4
// 我们定义的i是size_type类型,该类型没有符号,即使传入的参数是一个负数,也会被被强行修改(理解)为正数.
// 12.5
// 优点:编译器不会用这个构造函数来隐式转换,创建对象的时候我们能更清楚的知道自己使用的是哪一个构造函数.
// 缺点:让我们创建临时对象变得复杂.
return 0;
}
12.6 12,7 12.8 12.9
#include<iostream>
#include<string>
#include<vector>
#include<memory>
using namespace std;
vector<int>* func(){
return new vector<int>();
}
vector<int>* func2(vector<int>* p,istream& is){
int a;
while(is>>a)
p->push_back(a);
return p;
}
void print(vector<int>* p){
for(int i:*p)
cout<<i<<" ";
cout<<endl;
delete p;
}
shared_ptr<vector<int>> shared_func(){
return make_shared<vector<int>>();
}
void shared_func2(shared_ptr<vector<int>>p,istream& is){
int a;
while(is>>a)
p->push_back(a);
}
void shared_print(shared_ptr<vector<int>>p){
for(int i:*p)
cout<<i<<" ";
cout<<endl;
}
int main(){
// 12.6
vector<int>* vecp=func();
vecp=func2(vecp,cin);
print(vecp);
// 12.7
shared_ptr<vector<int>> sp=shared_func();
shared_func2(sp,cin);
shared_print(sp);
// 12.8
// 当函数返回时, int*类型要转换为bool类型,而在返回前为指针分配的内容并没有释放
// 函数返回后,将不再有机会释放那一段内存
// 12.9
int *q=new int(42), *r=new int(100);
r=q; //将r保存的地址赋值给q;q,r都指向int(42);(r原来保存的内容无法释放)
auto q2=make_shared<int>(42), r2=make_shared<int>(100);
r2=q2; //将q2保存的地址赋值给r2,r2原分配的内存没有智能指针指向它,被自动释放
return 0;
}
12.10 12.11 12.12 12.13
#include <iostream>
#include<vector>
#include <string>
#include<memory>
using namespace std;
void process(shared_ptr<int> q){
cout<<q.use_count()<<endl;
}
int main()
{
// 12.10
shared_ptr<int> p(new int(42));
cout<<p.use_count()<<endl;
process(shared_ptr<int>(p));
cout<<p.use_count()<<endl<<endl<<endl<<endl;
//正确, 创建临时智能指针作为参数时 use_count+1,调用过后指针销毁-1
//但自始至终p指向内存的use_count没有少于1,所以正确
// 12.11
process(shared_ptr<int>(p.get()));
// p会被销毁两次如P414解释的那样....(然而我的编译器并没有出现问题....)
// 12.12
auto p2=new int();
auto sp=make_shared<int>();
process(sp);
process(new int()); //错误,不能用构造函数隐式转换
process(p2); //错误,不能用构造函数隐式转换
process(shared_ptr<int>(p2));
// 12.13
// 会出现销毁两次内存(delete一次,智能指针自动销毁一次)
return 0;
}
12.14 12.15
#include<iostream>
#include<string>
#include<memory>
using namespace std;
struct destination{
string ip;
int port;
destination(string i,int p):ip(i),port(p){}
};
struct connection{
string ip;
int port;
connection(string i,int p):ip(i),port(p){}
};
connection connect(destination* d){
shared_ptr<connection>sp(new connection(d->ip,d->port));
cout<<"Start create connection to "<<d->ip<<":"<<d->port<<endl;
return *sp;
}
void disconnect(connection c){
cout<<"You have disconnected to "<<c.ip<<":"<<c.port<<endl;
}
void end_connection(connection* cp){
disconnect(*cp);
}
void f(destination& d){
connection c=connect(&d);
// shared_ptr<connection>sp2(&c,end_connection);
//12.15
shared_ptr<connection>sp2(&c,[](connection* cp){disconnect(*cp);});
cout<<"You have connected to "<<d.ip<<":"<<d.port<<endl;
}
int main(){
//12.14
destination d("192.168.1.5",3430);
f(d);
return 0;
}
12.16 12.17 12.18
#include<iostream>
#include<string>
#include<memory>
using namespace std;
int main(){
// 12.16
unique_ptr<int>a(new int(5));
// unique_ptr<int>c(a);
// unique_ptr<int>d=a;
// 拷贝 赋值 是同样的错误error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&)
// [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp> = std::unique_ptr<int>]'|
// 12.17
int ix=1024,*pi=&ix,*pi2=new int(2048);
typedef unique_ptr<int> IntP;
IntP p0(ix); //编译错误 类型不匹配
IntP p1(pi); //p1离开它的范围会自动调用delete 而pi并不是堆(new)上分配的内存.
IntP p2(pi2); //p2离开范围区自动销毁 ,让pi2变成了悬空指针
IntP p3(&ix); //同p1(pi)
IntP p4(new int(2048));
IntP p5(p2.get()); // 分配的内存会被释放两次
// 12.18
// shared_ptr可以直接拷贝复制给其他同类型智能指针,同时每个智能指针都能释放指向的对象
// 而unique则不行
return 0;
}
12.19 12.20 12.21 12.22
#include<iostream>
#include<vector>
#include<memory>
#include<string>
#include<stdexcept>
#include<fstream>
using namespace std;
// 12 19
class StrBlobPtr;
class StrBlob{
friend class StrBlobPtr;
public:
typedef vector<string>::size_type size_type;
StrBlob():data(make_shared<vector<string>>()){}
StrBlob(initializer_list<string>il):data(make_shared<vector<string>>(il)){}
size_type size()const{return data->size();}
bool empty(){return data->empty();}
void push_back(const string& str){data->push_back(str);}
void pop_back(){
check(0,"pop_back on empty StrBlob");
data->pop_back();
}
string& front()const
{
check(0,"front on empty StrBlob");
return data->front();
}
string& back()const
{
check(0,"back on empty StrBlob");
return data->back();
}
StrBlobPtr begin();
StrBlobPtr end();
private:
shared_ptr<vector<string>>data;
void check(size_type i,const string& msg)const{
if(i>=data->size())
throw out_of_range(msg);
}
};
class StrBlobPtr{
public:
StrBlobPtr():curr(0){}
StrBlobPtr(StrBlob& sb,size_t sz=0):wptr(sb.data),curr(sz){}
string& deref()const{
auto ret=check(curr,"dereference past end");
return (*ret)[curr];
}
StrBlobPtr& incr(){
check(curr,"increment past end of StrBlobPtr");
curr++;
return *this;
}
private:
weak_ptr<vector<string>>wptr;
size_t curr;
shared_ptr<vector<string>> check(size_t i,const string& msg)const{
auto ret=wptr.lock();
if(!ret)
throw runtime_error(msg);
if(i>ret->size())
throw out_of_range(msg);
return ret;
}
};
StrBlobPtr StrBlob::begin(){return StrBlobPtr(*this);}
StrBlobPtr StrBlob::end(){return StrBlobPtr(*this,this->size());}
int main(){
// 12.20
ifstream ifs("in.txt");
string str;
StrBlob sb;
while(getline(ifs,str))
sb.push_back(str);
StrBlobPtr st(sb.begin());
int length=sb.size();
while(length--){
cout<<st.deref()<<endl;
st.incr();
}
// 12.21
// std::string& deref()const{return (*check(curr,"dereference past end"))[curr];}
// 此版本效率上没有发生变化,减少了中间变量的申明,虽然代码空间变少,但可读性降低了,不易理解
// 12.22
// 需要给48行StrBlobPtr的构造函数参数加上const
// 需要给36 37行的操作加上const(书中调用这两个操作构造StrBlobPtr)
// StrBlobPtr(const StrBlob& sb,size_t sz=0):wptr(sb.data),curr(sz){}
return 0;
}
12.26
#include<iostream>
#include<string>
#include<memory>
using namespace std;
int main(){
// 12.26
const int n=25;
allocator<string>all;
string* p=all.allocate(n);
string s;
string *q=p;
while(cin>>s&&q!=p+n){
all.construct(q++,s);
}
size_t sz=q-p;
while(q!=p){
cout<<*--q<<endl;
all.destroy(q);
}
all.deallocate(p,sz);
return 0;
}
12.28 12.29
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<fstream>
#include<sstream>
using namespace std;
int main(){
//12.28
map<string,set<int>>mp;
vector<string>vec;
ifstream ifs("in.txt");
string temp,str;
int num=0;
while(getline(ifs,temp)){
++num;
vec.push_back(temp);
istringstream is(temp);
while(is>>str)
mp[str].insert(num);
}
while(1){
cout<<"please input a word :"<<endl;
cin>>str;
auto ret=mp.find(str);
if(ret==mp.end()){
cout<<"Not have this word"<<endl;
continue;
}
else{
cout<<"occurs:"<<ret->second.size()<<endl;
for(int i:ret->second)
cout<<i<<" ";
cout<<endl;
}
}
12.29
//此题两种类型的while效果一样,一般很少有人使用do while
return 0;
}
12.30 12.31
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<fstream>
#include<memory>
using namespace std;
class QueryReasult{
friend void print(ostream&,const QueryReasult&);
public:
QueryReasult(string str,shared_ptr<set<int>>p,shared_ptr<vector<string>>p2)
:sought(str),lines(p),file(p2){};
set<int>::iterator begin()const{
private:
string sought;
shared_ptr<set<int>>lines;
shared_ptr<vector<string>>file;
};
class TextQuery{
public:
TextQuery(ifstream& ifs):file(new vector<string>){
string line,str;
int num=0;
while(getline(ifs,line)){
++num;
file->push_back(line);
// cout<<111<<endl;
istringstream is(line);
while(is>>str){
shared_ptr<set<int>>& ret=wm[str];
if(!ret)
ret.reset(new set<int>);
ret->insert(num);
}
}
}
QueryReasult query(const string& str)const{
static shared_ptr<set<int>> nodata(new set<int>);
auto ret=wm.find(str);
if(ret==wm.end())
return QueryReasult(str,nodata,file);
return QueryReasult(str,ret->second,file);
}
private:
shared_ptr<vector<string>>file;
map<string, shared_ptr<set<int>> >wm;
};
void print(ostream& os,const QueryReasult& qr){
os<<qr.sought<<" occurs "<<qr.lines->size()<<endl;
for(auto i:*qr.lines)
cout<<"line"<<i<<": "<<(*qr.file)[i-1]<<endl;;
cout<<endl;
}
int main(){
// 12.30
ifstream infile("in.txt");
TextQuery tq(infile);
string str;
while(1){
cout<<"please input a word:"<<endl;
cin>>str;
print(cout,tq.query(str));
}
// 12.31
// 保存的下标会有重复 set更好,更简洁,不需要多余的代码和时间用来判断
return 0;
}
12.32 12.33
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<fstream>
#include<memory>
#include<stdexcept>
using namespace std;
class QueryReasult;
class StrBlob{
friend void print(ostream&,const QueryReasult&);
public:
typedef vector<string>::size_type size_type;
StrBlob():data(make_shared<vector<string>>()){}
StrBlob(initializer_list<string>il):data(make_shared<vector<string>>(il)){}
const string& get_string(int i){ //实在不会输出了 只好添加一个public函数
return (*data)[i];
}
size_type size()const{return data->size();}
bool empty(){return data->empty();}
void push_back(const string& str){data->push_back(str);}
void pop_back(){
check(0,"pop_back on empty StrBlob");
data->pop_back();
}
string& front()const{
check(0,"front on empty StrBlob");
return data->front();
}
string& back()const{
check(0,"back on empty StrBlob");
return data->back();
}
private:
shared_ptr<vector<string>>data;
void check(size_type i,const string& msg)const{
if(i>=data->size())
throw out_of_range(msg);
}
};
class QueryReasult{
friend void print(ostream&,const QueryReasult&);
public:
QueryReasult(string str,shared_ptr<set<int>>p,shared_ptr<StrBlob>p2) //修改构造函数
:sought(str),lines(p),file(p2){};
set<int>::iterator begin()const{ //12.33
return lines->begin();
}
set<int>::iterator end()const{ //12.33
return lines->end();
}
shared_ptr<StrBlob> get_file()const{ //12.33
return file;
}
private:
string sought;
shared_ptr<set<int>>lines;
shared_ptr<StrBlob>file; //修改成员
};
class TextQuery{
public:
TextQuery(ifstream& ifs):file(new StrBlob){ //修改构造函数
string line,str;
int num=0;
while(getline(ifs,line)){
++num;
file->push_back(line);
istringstream is(line);
while(is>>str){
shared_ptr<set<int>>& ret=wm[str];
if(!ret)
ret.reset(new set<int>);
ret->insert(num);
}
}
}
QueryReasult query(const string& str)const{
static shared_ptr<set<int>> nodata(new set<int>);
auto ret=wm.find(str);
if(ret==wm.end())
return QueryReasult(str,nodata,file);
return QueryReasult(str,ret->second,file);
}
private:
shared_ptr<StrBlob> file; //修改成员
map<string, shared_ptr<set<int>> >wm;
};
void print(ostream& os,const QueryReasult& qr){
os<<qr.sought<<" occurs "<<qr.lines->size()<<endl;
for(auto i:*qr.lines)
cout<<"line"<<i<<": "<<qr.file->get_string(i-1)<<endl; //调用get_string
cout<<endl;
}
int main(){
// 12.32
ifstream infile("in.txt");
TextQuery tq(infile);
string str;
while(1){
cout<<"please input a word:"<<endl;
cin>>str;
print(cout,tq.query(str));
}
return 0;
}