普通指针的不足
- new和new[]的内存需要用delete和delete[]释放。
- 程序员的主观失误,忘了或漏了释放。
- 程序员也不确定何时释放。
普通指针的释放
- 类内的指针,在析构函数中释放。
- C++内置数据类型,如何释放?
- new出来的类,本身如何释放?
指针指针的设计思路
-
智能指针是类模板,在栈上创建智能指针对象。
-
把普通指针交给智能指针对象。
-
智能指针对象过期时,调用析构函数释放普通指针的内存。
智能指针的类型
- auto_ptr是C++98的标准,C++17已弃用。
- unique_ptr、shared_ptr和weak_ptr是C++11标准。
智能指针unique_ptr
unique_ptr独享它指向的对象,也就是说,同时只有一个unique_ptr指向同一个对象,当这个unique_ptr被销毁时,指向的对象也随时被销毁。
包含头文件:#include <memory>
示例
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class AA
{
public:
string m_name;
AA(){cout << "init AA " << endl;}
AA(const string& name):m_name(name){cout << "init AA and param " << endl;}
~AA(){cout << "desctory AA" << endl;}
}
int main()
{
//第一种方式
AA* P=new AA("aaa");
unique_ptr<AA> pu1(p);
cout << "m_name" << (*pu1).m_name << endl;
cout << "m_name" << pu1.m_name << endl;
//第二种方式
unique_ptr<AA> pu2=make_unique<AA>("aaa");
//第三方方式
unique_ptr<AA> pu3=make_unique<AA>(new AA("aaa"));
}
-
将一个unique_ptr赋给另一个时,如果源unique_ptr是一个临时右值,编译器允许这样做;如果源unique_ptr将存在一段时间,编译器禁止这样做。一般用于函数的返回值。
unique_ptr<AA> p0;
p0=unique_ptr<AA>(new AA("aaa"));
-
用nullptr给unique_ptr赋值将释放对象,空的unique_ptr==nullptr;
-
release()释放对指针的控制权,将unique_ptr置为空,返回裸指针。(可用于把unique_ptr传递给子函数,并且在子函数中释放对象)
-
std::move()可以转移对指针的控制权。(可用于把unique_ptr传递给子函数,子函数形参也是unique_ptr)
-
reset()释放对象
void rest(T* _ptr=(T*)nullptr);
pp.reset(); //释放pp对象指向的资源对象
pp.reset(nullptr); //释放pp对象指向的资源对象
pp.reset(new AA("bbb")); //释放pp指向的资源对象,同时指向新的对象
-
swap()交换两个unique_ptr的控制权
void swap(unique_ptr<T> &_Right);
-
unique_ptr也可像普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样。
-
unique_ptr不是绝对安全,如果程序中调用exit()退出,全局的unique_ptr可自动释放,但局部的unique_ptr无法释放。
-
unique_ptr提供了支持数组的具体化版本。
数组版本的unique_ptr,重载了操作符[],操作符返回的引用,可以作为左值使用。
智能指针shared_ptr
shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,在内部采用的计数机制来实现。
当心的shared_ptr与对象关联时,引用计数增加1;
当shared_ptr超出作用域时;引用计数减1。当引用计数变为0,则表示没有任何shared_ptr与对象关联,则释放该对象。
基本用法
shared_ptr的构造函数也是explicit,但是,没有删除构造函数和赋值函数。
初始化
方法一:
shared_ptr<AA> p0(new AA("aaa"));
方法二:
shared_ptr<AA> p0=make_shared<AA>("aaa");
方法三:
AA* p=new AA("aaaa");
shared_ptr<AA> p0(p);
方法四:
shared_ptr<AA> p0(new AA("aaa"));
shared_ptr<AA> p1(p0);
shared_ptr<AA> p2=p1;
智能指针weak_ptr
shared_ptr存在的问题
shared_ptr内部维护一个共享的引用计数器,多个shared_ptr可以指向同一个资源。
如果出现了循环引用的情况,引用计数永远无法归0,资源不会被释放。
weak_ptr没有重载->个*操作符,不能直接访问资源。
有以下成员函数:
1)operator=() //把shared_ptr或weak_ptr赋值给weak_ptr;
2)expired(); //判断它指资源是否已过期(已经被销毁);
3)lock();//返回shared_ptr,如果资源已经过期,返回空的shared_ptr。
4)reset (); //将当前weak_ptr指针置为空。
5)swap(); //交换
智能指针的删除器
在默认情况下,智能指针过期的时候,用delete原始指针;释放它管理的资源。程序员可以自定义删除器,改变智能指针释放的资源的行为。删除器可以时全局函数、仿函数和Lambda表达式,形参为原始指针。
void deleteFunc(AA* a)
{
delete a;
}
int main()
{
shared_ptr<AA> pa1(new AA("aaa"),deleteFunc);
return 0;
}
网友评论