(1.1)指针的小介绍
int b = 9;
int *a = &b;
cout<< "a="<
a)
裸指针: 直接用new返回的指针
b)智能指针:对裸指针进行了包装的指针 ,优点:能够自动释放所指向的对象内存
C++标准库有四种智能指针:auto_ptr(C++98已有) unique_ptr
shared_ptr weak_ptr(后三个C++11)
目前auto_ptr已经完全被unique_ptr取代了 已经被委员会反对使用了
帮助我们进行动态分配的生命周期管理,能够有效防止内存泄漏
shared_ptr
共享式指针 ,多个指针指向同一个对象,最后一个指针被销毁时,内存被释放
weak_ptr
是辅助shared_ptr的
unique_ptr
独占式指针,同一时间内,只有一个指针指向一个对象 所有权还是可以转移的
shared_ptr
最后一个shared_ptr在什么情况下才能释放该对象呢?
a)这个 shared_ptr 被析构的时候
b)这个shared_ptr 指向其他对象时
格式: shared_ptr<指向的类型>智能指针名
(1.3)shared_ptr智能指针的初始化
1、
shared_ptrp_a(new int(100));//p_a指向一个值为100的数据
这是显式类型转换
shared_ptrp_b= new int(200);//;智能指针是显示类型装换,这个等号是隐式类型装换,必须直接初始化使用,这样写就是不行的
2、
shared_ptr make(int value)
{
return shared_ptr(new int(value));//必须这样返回
}
shared_ptrp_3 = make(200);这样写也可以
3、
//可以使用裸指针初始化智能指针,但是不要穿插使用,就是不要再使用裸指针
int *p = new int(300);
shared_ptrp_4(p);
4、 shared_ptrp_4_4;//初始化一个智能指针,但是指向为空(nullptr)
5、
//make_shared函数 标准库里的函数模板,安全,高效地使用shared_ptr
//它能够在动态内存中分配并初始化一个对象,然后返回指向该对象的shared_ptr
shared_ptrp_5 =make_shared(100);//与new有一点类似,但返回智能指针的类型
shared_ptrp_6 =make_shared(5,'q');
shared_ptrp_7=make_shared();//值初始化,为0
p_7= make_shared(700);//p_7指向一个新内存, 它先释放刚才指向的内存,再指向新的内存
(1.4)shared_ptr函数相关
shared_ptr myfunc(shared_ptr&temp)
{
return temp;
}
(1.5)shared_ptr的引用计数
共享式,引用计数,每一个shared_ptr的拷贝都指向相同的内存,只有最后一个指向该对象的shared_ptr不需要指向的时候,这个shared_ptr才会析构所有对象
(1.5.1)引用计数的增加
每一个shared_ptr都会记录多少个其他shared_ptr指向相同的对象
auto p6 =
make_shared(100);//目前只有p6一个引用者指向100
auto p7(p6);//智能指针的初始化,p7和p6指向了相同的对象,此对象目前有两个引用者
这个情况下,所有指向该对象的shared_ptr的引用计数增加一 [2 strong ref]
(1.5.2)在下面几种情况下,引用计数会增加
a)比如上面一样,用p6初始化p7
b)把智能指针当初实参往函数里传递
myfunc(p7);//如果就直接传递,就变成3,引用传递,就还是2
c)作为函数的返回值
auto p8 = myfunc(p7);
myfunc(p8);//如果没有接的话,就当场析构掉,就不会增加
(1.5.3)引用计数减少
//a)给shared_ptr赋新值
p8= make_shared(200);//p8指向新对象,原计数变成2
p7= make_shared(300);//p7指向新对象,原计数变成1
p6= make_shared(400);//p6指向新对象, 原对象被释放
//可以通过查看内存来观察,注:变红就因为被释放了
//b)局部的shared_ptr离开其作用域
myfunc(p6);//进入时为3个,但是栈空间被销毁之后,就是两个了
(1.6)shared_ptr指针的常用操作
(1.6.1)use_count()返回多少个智能指针指向该对象,主要用于调试目的
shared_ptrmyp(new int(100));
cout<< myp.use_count() << endl;//返回个数
(1.6.2)unique() 是否该智能指针是否独占该对象,如果是的话就返回ture,不是的话就返回否
shared_ptrmyp3(new int(200));
if (myp3.unique())
{
cout<< "是" << endl;
}
else
{
cout<< "否" << endl;
}
(1.6.3)reset()
恢复或者复位的意思
reset()不带参数时,
若pi是唯一指向该对象的指针,那么释放pi指向的对象,并将pi置空
若pi不是唯一指向该对象的指针,那么不释放pi锁指向的对象,但指向该对象的引用计数会减少,同时将pi置空
shared_ptrpi(new int(230));
pi.reset();
if (pi==nullptr)
{
cout<< "pi被置空" << endl;
}
else
{
cout<< "pi没被置空" << endl;
}
reset()带参数时,(一般是一个new出来的指针)时
若pi是唯一指向该对象的指针,则释放pi指向的对象,让pi指向新对象
若pi不是唯一指向该对象的指针,则不释放pi指向的对象,但是指向该对象的引用计数会减少
1,同时让pi指向新对象;
shared_ptrpi3(new int(1));
pi3.reset(new int(2));//查看内存即可了解
//空指针也可以用它来初始化
shared_ptrp4;
p4.reset(new int(120));
(1.6.4)解引用,获取p4指向的对象
cout << p4 << endl;
cout << *p4 << endl;
(1.6.5)swap()交换两个智能指针所指向的对象
shared_ptrsw(new string(“hello”));
shared_ptrss(new string("myword"));
sw.swap(ss);
cout<< *sw << endl;
cout<< *ss << endl;
//或者这样写
swap(ss,sw);
(1.6.6)=nullptr
将所指向的对象引用计数减一,若引用计数为0,则释放智能指针所指向的对象
将智能指针置空
shared_ptrnu(new string("hi"));
shared_ptrnl(nu);
nu= nullptr;
(1.6.7)智能指针名字作为判断条件
shared_ptrpan(new int(21));
if (pan)
{
cout<< “不为空” << endl;
}
else
{
cout<< “为空” << endl;
}
(1.6.8)指定删除器以及数组问题
(1.6.9)shared_ptr的注意事项
void proc(shared_ptrp)
{
return;
}
int *d = new int(12);
proc(d);是不行的,语法错误,int*d不能转换成shared_ptr,要临时转换
proc(shared_ptr(d));//如果这样写了之后,就不要再使用裸指针了,因为它的生命周期交给了智能指针,
不能使用裸指针初始化多个内存,
int *q = new int(12);
shared_ptrq_1(q);//它们两个都是只有一个强引用,说明它们没有汇通,程序结束后会delete两次该内存
shared_ptrq_2(q);
慎用get()返回的裸指针
(有些接口只能使用裸指针)
get返回的裸指针不能自己delete
shared_ptrdde(new int(12));
int *q_11 =dde.get();
delete q_11;
不能把其他智能指针绑定到get()返回的裸指针上
shared_ptrbangding(q_11);//也是不会汇通,容易delete两次
永远不能用get()得到的裸指针初始化或赋值
//(3.2)移动语义
shared_ptrv_1(new int(11));
shared_ptrv_2(move(v_1));//移动后v_1就为空
(2.7)unique_ptr概述
独占式的概念(专属所有权)同一时刻,只能有一个unique_ptr指针指向该对象(这块内存)
当这个unique_ptr被销毁时,这个指向的内存也会被销毁
unique_ptr<对象类型>变量名
(2.8)unique_ptr常规初始化
unique_ptru_1;
if (u_1 == nullptr)
{
cout<< "这个内存还没有初始化" << endl;
}
unique_ptru_2(new int(12));
//(1.2)make_unique函数
C++14的
unique_ptru_3 =make_unique(123);
//auto u_4(u_3);不能赋值啦 不支持拷贝操作
auto u_4(move(u_3));//但是移动可以
(1.9)relase( )
放弃对指针的控制权(切断了智能指针与其所指向的对象的联系)
//返回裸指针,并将裸指针置空
int *a = u_4.release();
cout<< *a << endl;
//或者用它来初始化
unique_ptru_5 =
make_unique(123);
auto u_6(u_5.release());
(1.10)reset()
//(2.3)reset 不带参数就置空,带参数就指向新对象,原来的置空
auto p_7 =make_unique(11);
auto p_8 =make_unique(111);
p_7.reset(p_8.release());//不会内存泄漏,可以去MFC尝试
(1.11)=nullptr
释放智能指针所指向的对象,并将智能指针置空
p_7= nullptr;
(1.12)指向一个数组
unique_ptrptrarr(new int[10]);//不需要自己写删除器
ptrarr[0] = 11;
ptrarr[1] = 22;
ptrarr[2] = 23;