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;
}
网友评论