[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 << 
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++中,`unique_ptr`、`shared_ptr`、`weak_ptr`是三种常用的智能指针,用于管理动态分配的内存,避免内存泄漏和悬空指针等问题。 1. `unique_ptr`:是一种独占式智能指针,表示一个对象的所有权只能被一个`unique_ptr`持有,不能被其他指针或引用所共享。当`unique_ptr`超出作用域或被显式释放时,它所指向的对象将被自动销毁。例如: ```cpp std::unique_ptr<int> p(new int(10)); ``` 2. `shared_ptr`:是一种共享式智能指针,表示一个对象的所有权可以被多个`shared_ptr`共享。每个`shared_ptr`维护一个引用计数器,当引用计数器变为0时,它所指向的对象将被自动销毁。`shared_ptr`还支持自定义删除器,可以在对象销毁时执行特定的操作。例如: ```cpp std::shared_ptr<int> p = std::make_shared<int>(10); std::shared_ptr<int> q = p; ``` 3. `weak_ptr`:是一种弱引用智能指针,不能直接访问所指向的对象,只能通过调用`lock()`方法获得一个指向所指对象的`shared_ptr`。当`weak_ptr`所指向的对象已经被销毁时,`lock()`方法将返回一个空的`shared_ptr`。`weak_ptr`主要用于解决`shared_ptr`的循环引用问题,避免内存泄漏。例如: ```cpp std::shared_ptr<int> p = std::make_shared<int>(10); std::weak_ptr<int> q = p; std::shared_ptr<int> r = q.lock(); ``` 这些智能指针都定义在`<memory>`头文件中,并且都是模板类,可以用于管理各种类型的动态分配内存。在实际开发中,应尽量使用智能指针来管理内存,避免手动管理内存所带来的麻烦和风险。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值