智能指针模板类

2023-02-26 10:53:55 浏览数 (1)

智能指针是行为类似于指针的类对象,但这种对象还有其他功能。使用指针指向一块新申请的内存的过程中,有时忘记释放新申请的内存,导致内存泄漏。为了防止该问题的发生,C 提供了智能指针模板类。其思想就是将常规的指针变成一个类对象,该对象主要实现常规指针的功能,当该对象过期的时候,会自动调用其析构函数,在析构函数中完成内存释放的操作。

智能指针有auto_ptrunique_ptrshared_ptrweak_ptr(本章暂时不做详细介绍),其中auto_ptr在C 11中摒弃。

代码语言:javascript复制
class A{...};
void fun()
{
    A* pa = new A;
    std::auto_ptr<A> p1 = new A;
    std::unique_ptr<A> p2 = new A;
    std::shared_ptr<A> p3 = new A;
    ...
    delete pa; //必须在pa过期之前释放分配的内存
    //delete p1;//不需要手动释放内存,在p1过期的时候,会自动调用其析构函数释放对应的内存块
    //delete p2;//不需要手动释放内存,在p2过期的时候,会自动调用其析构函数释放对应的内存块
    //delete p3;//不需要手动释放内存,在p3过期的时候,会自动调用其析构函数释放对应的内存块   
}

有关智能指针的注意事项

常规的指针在使用的过程中两个指针可能会指向同一个对象,这是不能接受的,因为程序在结束的时候会存在删除同一对象两次的问题,如下例:

代码语言:javascript复制
std::string* ps (new std::string("abc"));
std::string* p1;
p1 = pa;  
...
delete ps;
delete pa;

针对上述问题,auto_ptrunique_ptr在常规指针的基础上增加了所有权的概念,对于特定对象,只有一个指针可以拥有它,这样只有拥有对象的智能指针才能删除该对象。

shared_ptr采用跟踪引用特定对象的智能计数(即引用计数)策略。例如,赋值的时候,计数加1,而指针过期的时候,计数减1,仅当最后一个指针过期的时候才调用delete

下面我们举个例子,看一下他们之间的区别。

代码语言:javascript复制
auto_ptr<std::string> p1(new std::string("abc"));
auto_ptr<std::string> p2;
p2 = p1;    //p2接管string对象的所有权后,p1的所有权被剥夺,其不再指向有效数据,后面如果尝试调用p1,程序运行的时候则会导致程序core dumped

unique_ptr<std::string> p1(new std::string("abc"));
unique_ptr<std::string> p2;
p2 = p1;    //p2接管string对象的所有权后,p1的所有权被剥夺,其不再指向有效数据,后面如果尝试调用p1,则编译失败

shared_ptr<std::string> p1(new std::string("abc"));//引用计数器为1
shared_ptr<std::string> p2;
p2 = p1; //引用计数器为2
//在p1、p2过期的过程中,计数器相应减1,当最后一个智能指针过期的时候,调用修购函数时,将引用计数器降低到0,并释放对应的空间

从上面的例子可以看出unique_ptrauto_ptr最大的区别就在于当一个智能指针的所有权被剥夺后,若后面的程序要调用它的时候,unique_ptr直接在编译阶段就失败,将问题暴露出来,而auto_ptr编译阶段不会报错,在程序运行的时候出现异常,因此unique_ptr的安全性更高(编译阶段错误比程序崩溃更安全)。

相比auto_ptrunique_ptr另外一个优点就是它有一个可以用于数组的变体。我们知道deletenew配对,delete[]new[]配对,而auto_ptr中使用的是delete,而不是delete[],因此只能与new一起使用,不能与new[]一起使用。但unique_ptrdeletedelete[]两个版本,它可以与new一起使用,也可以与new[]一起使用。同样的,shared_ptr也支持与new一起使用,不支持new[]的使用。

:使用new分配内存时,可以使用auto_ptrunique_ptrshared_ptr;使用new[]分配内存时,不能使用auto_ptrshared_ptr,可以使用unique_ptr;不使用newnew[]分配内存时,不能使用unique_ptr

如何选择合适的指针

  • 程序要使用多个指向同一个对象的指针 使用shared_ptr
  • 程序不需要多个指向同一个对象的指针 使用unique_ptr

0 人点赞