1.智能指针
智能指针是一个可以模仿原生指针的模板类,与原生指针有两点区别:
- 1智能指针只能用来保存堆上分配的内存
- 2不能像对原生指针那样,对智能指针进行一些自增或自减之类 的算术运算
智能指针自动释放不需要的对象,消除了内存泄露的可能性。
通常在自由存储区创建的对象使用智能指针而不是原生指针。
可以在容器中使用智能指针,如果使用一个类的基类作为智能指针的类型参数,可以用它指向一个派生类对象。
std空间中有3中不同类型的智能指针模板:
- unique_ptr 读特的,不可能有其他的unique_ptr指向同一个地址,一个unique_ptr完全拥有它所指向的内容,不能指定或复制一个unique_ptr对象,可以通过utility头文件中的std::move函数来一出一个unique_ptr对象所指向的地址,move后之前的unique_ptr变为无效。
当一个对象呗unique_ptr指向时,也可以通过原生指针来访问对象。 - shared_ptr,多个shared_ptr可以指向同一个地址,允许共享一个对象的所有权。当一个新的shared_ptr指针指向一个特定堆地址时引用计数+1,当一个shared_ptr释放或指向了新的地址时,引用计数-1,当引用计数变为0时,在堆上为这个对象分配的内存就会制动释放,所有指向同一个地址的shared_ptr都可以得到引用计数的值
- weak_ptr可以从一个shared_ptr对象创建,它们指向相同的地址,创建一个weak_ptr不会增加shared_ptr对象的引用计数,所以它会阻止指向对象的销毁,当最后一个shared_ptr引用的对象被释放或者只想一个不同的地址时,它们所指向的对象的内存会被释放,即使相关的weak_ptr可能仍然存在。使用weak_ptr的主要原因是,我们可能在不经意间创建一个循环引用。循环引用从概念上说就是一个shared_ptr对象pA,指向了另一个shared_ptr对象PB,在这种情况下,两个对象都不能被释放。通过使用weak_ptr指向一个shared_ptr对象
2.使用unique_ptr
- 创建
unique_ptr pname{new string{" sfsfsfsf"}};
unique_ptr up=make_unique(“adfjskll”);//更好, unique_ptr也可以替换为auto类型 - 访问
- get()方法 stringpstr={up.get()};
- 重置
当智能指针析构时, unique_ptr所指向的对象也会被析构。
可以调用release函数析构智能指针所指向的对象,但不析构智能指针
p.reset(new string{“Fred”});//析构智能指针原本指向的对象,但不析构智能指针并使其指向新的对象
p.reset()//将智能指针对象中的原生指针替换为空指针,析构所指对象
3.使用shared_ptr
- shared_ptr sp{new string{“jdlkg”}};
shared_ptr sp=make_shared(“dsg”);//类型也可以用auto - sp,reset()//会使智能指针所指向的原生指针为空,同时时期对象的引用计数-1
sp.reset(new string{“23242”});//指向新对象 - sp.unique()//如果对象的引用计数为1 返回true
- sp.use_count()//返回所指对象的引用计数
4 .使用weak_ptr
-
weak_ptr对象只能从shared_ptr创建
auto pda=make_shared();
weak_ptr pwda(pdata);//从shared_ptr对象创建
weak_ptr pwda2(pwda)//从weak_ptr对象创建
当shsred_ptr类型的指针ABCD构成循环引用时,删除ABCD指针或者将他们重置为空并不能释放他们所指向对象的内存,因为每个对象仍有一个shared_ptr指向他们所以无法销毁。
如果对象使用weak_ptr作为成员变量来指向其他的对象,就可以解决这个问题,当外部数组中的指针被销毁或重置时,Weak_ptr不会阻止对象的销毁。 -
不能以解引用的方式访问weak_ptr所指的对象。
-
可以使用weak_ptr做一下两件事:
1 可以判断它所指向的对象是否认若干存在,即仍然有shared_ptr指向它
2 可以从一个weak_ptr对象创建一个shared_ptr对象 -
判断weak_ptr所指向的对象是否仍然存在weak_ptr.expired()//不存在返回true
shared_ptr pnew{pwda.lock()};//如果pwda指向的对象仍然存在,lock函数会返回一个具有空指针的shared_ptr对象