[C++]智能指针unique_ptr,shared_ptr,weak_ptr

C++中对于动态内存的使用非常严格,一次申请必须对应一次释放,否则将造成内存泄漏。这也要求程序员格外小心,比如如下示例:

void getStr() {
   
   
    std::string * pstr = new std::string();//pstr为局部变量
    *pstr = "Hello world";
    ....
    return;
}

当该方法执行完毕后,局部变量pstr所占用内存自动释放,但其指向的内存则一直驻留。必须通过delete pstr来释放,因此这里将造成内存泄漏。

还有一种情况就是当程序因异常而终止时:

#include <stdexcept>

void getStr() {
   
   
    char * pch = new char[1024];
    ...
    if (true)
        throw logic_error("throw a exception");
    delete [] pch;
}

虽然在这里没有忘记delete释放内存,但是当程序执行到throw时,将不再执行throw之后的语句,因此导致内存泄漏。针对于这个例子,虽然可以通过如下的方式避免这个问题,但依旧需要非常小心:

#include <stdexcept>

void getStr() {
   
   
    char * pch = new char[1024];
    ...
    if (true)
    try{
   
   
        throw logic_error("throw a exception");
    } catch(...){
   
   
        delete [] pch;
        throw;
    }
    delete [] pch;
}

为了让程序员不再因内存泄漏而操心,C++11中提供了几个用于动态内存管理的智能指针。

智能指针的原理

如果在指针对象过期时,让它的析构函数删除它指向的内存,那不就避免内存的泄漏了吗?比如当自动变量pstr被销毁时,让他的析构函数可以释放它指向的内。

智能指针正是采用这种方式实现的,在智能指针类中,定义了类似指针的对象,然后将new获得的地址赋给这个对象,当智能指针过期后,其析构函数将使用delete来释放这块内存。

使用智能指针

智能指针模板类位于头文件memory中,因此使用时必须包含该头文件。memory中提供了四种智能指针模板类:auto_ptr,unique_ptr,shared_ptr,weak_ptr,其中auto_ptr在C++11中被弃用,在C++17中被移除,因此主要学习其余三种。

unique_ptr

unique_ptr类模板如下:

template<class T, class Deleter = std::default_delete<T>> 
class unique_ptr;

template <class T,class Deleter> 
class unique_ptr<T[], Deleter>;

因此,unique_ptr有两个版本:

  • 1.管理个对象(以 new 分配)
  • 2.管理动态分配的对象数组(以 new[] 分配)

构造方法

unique_ptr的构造方法有多个,但常用如下几个个:

constexpr unique_ptr() noexcept;
constexpr unique_ptr (nullptr_t) noexcept : unique_ptr() {
   
   }
explicit unique_ptr(pointer p) noexcept;

unique_ptr通过建立所有权概念来管理对象,也就是说,对于特定的对象,只能有一个智能指针可以拥有它。因此:

  • 1.不能使用一个unique_ptr对象来初始化另一个unique_ptr对象,其拷贝构造不可用:unique_ptr (const unique_ptr&) = delete;
  • 2.不能使用一个unique_ptr对象来给另一个unique_ptr赋值,其赋值运算符不可用:unique_ptr& operator= (const unique_ptr&) = delete.

然而,当试图将一个unique_ptr对象赋给另一个unique_ptr时,如果源unique_ptr是一个临时右值,则编译器允许这样做,如:

std::unique_ptr<Person> get_uptr(Person* p) {
   
   
        std::unique_ptr<Person> temp (p);
        return temp;
}
std::unique_ptr<Person> uptr4 = get_uptr(new Person("XiaoWang"));

这是通过移动构造来区分的。

如果需要将一个unique_ptr对象赋给另一个unique_ptr,则使用std::move()函数;

成员函数

  • get():返回指向被管理对象的指针。
  • reset():替换被管理对象;
  • release(): 返回一个指向被管理对象的指针,并释放所有权.
  • swap():替换被管理对象;
  • operator bool:检查是否有关联的被管理对象.

下面为使用unique_ptr示例:

#include <iostream>
#include <memory>
#include <string>

class Person
{
   
   
private:
        std::string name;
public:
        Person(const std::string& name):name(name){
   
   
                std::cout << "Person " << name 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值