C++ 智能指针


智能指针:shared_ptr类

shared_ptr是一个模板类,智能指针本质是个对象,有一些方法可以调用。

shared_ptr p;
p.get();//获得指针的值(内存地址)
p.use_count();//有几个智能指针指向这个内存地址
p.unique();//如果p.use_count()==1,他返回true

这个类也定义了解引用运算符(*)和箭头运算符(->),目的是像使用指针一样使用智能指针。

*p;
p->func();//等价(*p).func();

make_shared() 函数

智能指针有三种初始化方式

shared_ptr p(new int);//用new返回的指针来初始化,但这个构造函数是explicit的,因此,普通指针无法隐式转换成智能指针。
shared_ptr q(p);//用另一个智能指针初始化
shared_ptr p(make_shared(10)); //使用make_shared();他也是一个模板,需要指定类型,后边的括号相当于调用构造函数
//也可以用auto
auto p = make_shared(10);

动态内存会随着智能指针的生命周期而自动释放,当没有一个智能指针指向某块内存,他就会自动释放。也就是p.use_count() == 0,当然这个代码不可能运行成功,只是方便理解。

注意事项:

  1. 不要混用智能指针和普通指针,你很难注意智能指针什么时候会自动释放,这时再用普通指针访问会发生错误。

  2. 不要用智能指针的get()函数来初始化另一个智能指针,这种方法不会增加use_count,因此会double free。

    int main()
    {
    	shared_ptr p(make_shared());
    	shared_ptr q(p.get());
    	cout << p.use_count();//输出1
    	getchar();
    	return 0;
    	//程序结束p和q都会释放内存,double free
    }
    

使用自己的释放操作

引用C++ primer里的例子,假如shared_ptr指向的是一个网络连接,那么我们希望当这个连接不再使用的时候能够自动释放,这就需要自己定义释放函数。

void end_connection(connection *p)
{
    //释放连接
}
void f(destination &d)
{
    connection c = connect(d);
    shared_ptr p(&c, end_connection);
    //使用连接
    //从f退出时,connection会自动调用end_connection关闭
}

unique_ptr

shared_ptr智能指针可以不同的几个智能指针指向同一块内存,而unique_ptr只允许一个智能指针(不管是shared_ptr还是unique_ptr)指向这块内存。要想将这块内存变成普通的智能指针,使用p.release()。

unique_ptr up(new T);
shared_ptr sp(up.release());
up.reset(new int);//重新绑定一个内存地址

unique_ptr使用自己的释放操作

unique_ptr p(new T, d);
//D是可调用对象的类型,d是D类型的一个对象
//下边是个例子
void end_connection(connection *p)
{
    //释放连接
}
void f(destination &d)
{
    connection c = connect(d);
    unique_ptr p(&c, end_connection);
    //使用连接
    //从f退出时,connection会自动调用end_connection关闭
}

相关