[C++] 智能指针(shared_ptr、unique_ptr)

简介: [C++] 智能指针(shared_ptr、unique_ptr)

📢前言

      智能指针是行为类似于指针的类对象,单这种对象还有其他功能。本文介绍三个可帮助管理动态内存分配的智能指针类。先来看看需要哪些功能以及这些功能是如何实现的。请看下面的函数:

void remodel(std::string & str)
{
    std::string * ps = new std::string(str);
    ...
    str = ps;
    return;
}

      您可能发现了其中的缺陷。每当调用时,该函数都分配堆中的内存,单从不回收,从而导致内存泄漏。您可能也知道解决之道——只要别忘了在return语句前添加下面的语句,以释放分配的内存即可:

delete ps;

      然而,但凡涉及“别忘了”的解决方法,很少是最佳的。因为您有时可能忘了,有时可能记住了,但可能在不经意间深处或注释掉了这些代码。即使确实没有忘记,也可能有问题。请看下面的变体:

void remodel(std::string & str)
{
    std::string * ps = new std::string(str);
    ...
    if (weird_thing())
        throw exception();
    str = *ps;
    delete ps;
    return;
}

      当出现异常时,delete将不被执行,因此也将导致内存泄漏。

      如果ps有一个析构函数,该析构函数将在ps过期时释放它指向的内存,那么问题就解决了。因此,ps的问题在于,它只是一个常规指针,不是有析构函数的类对象。如果它是对象,则可以在对象过期时,让它的析构函数删除指向的内存。这正式auto_ptr、unique_ptr和shared_ptr背后的思想。模板shared_ptr允许多个指针指向同一个对象unique_ptr独占一个对象。定义在meory头文件中模板auto_ptr是C++98提供的解决方案,C++11已将其摒弃。然而,虽然auto_ptr被摒弃,单它已经使用了多年;同时,如果您的编译器不支持其他两中解决方法,auto_ptr将是唯一的选择方案。

总结:为什么使用智能指针?

      new申请动态内存,delete释放动态内存,注意有new必须要有相应的delete删除内存,不然会产生内存泄漏问题。为了解决这种内存泄漏问题,标准库包含两种智能指针(unique_ptr和shared_ptr),其可以自动释放内存。


✨动态内存与智能指针

      这三个只能指针模板(auto_ptr/unique_ptr和shared_ptr)都定义了类似指针的对象,可以将new或make_shared获得(直接或间接)的地址赋给这种对像。当只能指针过期时,其析构函数将使用delete来释放内存。因此,如果将new或make_shared返回的地址赋给这些对像,将无需记住稍候释放这些内存:在智能指针过期时,这些内存将自动被释放。

💫智能指针—shared_ptr

定义shared_ptr,定义和其它的模板类似,需要使用<>,默认初始化时会产生空指针。

shared_ptr<int>p1;        //p1为指针,指向string类型
shared_ptr<vector<int>>p2;//p2为指针,指向int的vector

一、分配和使用动态内存的方法:

1)使用new返回地址

std::shared_ptr<Test> p(new Test);

      很显然这段代码会引起一个内存分配,但实际上是有两次内存分配。条款19解释了每个std::shared_ptr会指向一个控制块,这个控制块除了其他一些东西,包含了所指对象的引用计数。控制块的内存分配是在std::shared_ptr的构造函数中进行的。这样直接用new需要为Widget来分配一次内存,还要为控制块再分配一次内存。

2)使用std::make_shared来代替new返回地址

std::shared_ptr<Test> p = std::make_shared<Test>();

      这样一次内存分配就足够了。那是因为std::make_shared会分配一块独立的内存既保存Widget对象又保存控制块。 这个优化减小了程序的静态尺寸,因为代码只包含一次内存分配的调用,同时增加了代码执行速度,因为只有一次内存分配。

总结:make_shared要优于使用new,make_shared可以一次将需要内存分配好,返回一个shared_ptr指针。在memory中定义,是最安全的分配和使用动态内存的方法。

注:要创建智能指针对象,必须包含头文件memory,该文件模板定义。然后使用通常的模板语法来实例化所需类型的指针。

此外,智能指针有一个get函数,可以得到shared_ptr指向对象的内置指针

std::shared_ptr<int>p(new int(2));
int *q=p.get();//q为一个内置指针,指向和p同一个对象,注意不要delete q

💥智能指针—unique_ptr

和shared_ptr不同,unique_ptr拥有它所有的唯一对象,这样就保证unique_ptr被销毁时,其对象也会被销毁。

只能使用new进行直接初始化,不支持普通拷贝和赋值。

std::unique_ptr<int>p1(std::make_shared<int>(2));//直接初始化
std::unique_ptr<int>p2;
p2=p1;//错误,不能同时指向一个对象

但可以所有权转移,使用reset或release。

unique_ptr<int>p1(new int(2));
unique_ptr<int>p2(p1.release());//release会将p1置为空,就是切断p1和它对象的联系
unique_ptr<int>p3(new int(1));
p2.reset(p3.release());//将p3置空并转权给p2;

 


戳戳小手帮忙点个免费的赞和关注吧,嘿嘿。

其他相关描述:C++智能指针shared_ptr、unique_ptr以及weak_ptr

目录
相关文章
|
4月前
|
存储 安全 C++
C++ 11新特性之unique_ptr
C++ 11新特性之unique_ptr
111 4
|
4月前
|
C++
C++(十八)Smart Pointer 智能指针简介
智能指针是C++中用于管理动态分配内存的一种机制,通过自动释放不再使用的内存来防止内存泄漏。`auto_ptr`是早期的一种实现,但已被`shared_ptr`和`weak_ptr`取代。这些智能指针基于RAII(Resource Acquisition Is Initialization)原则,即资源获取即初始化。RAII确保对象在其生命周期结束时自动释放资源。通过重载`*`和`-&gt;`运算符,可以方便地访问和操作智能指针所指向的对象。
|
4月前
|
安全 C++ 开发者
C++ 11新特性之shared_ptr
C++ 11新特性之shared_ptr
35 0
|
5月前
|
安全 NoSQL Redis
C++新特性-智能指针
C++新特性-智能指针
|
5月前
|
安全 编译器 容器
C++STL容器和智能指针
C++STL容器和智能指针
|
5月前
|
C++
【C++】智能指针
【C++】智能指针
|
5月前
|
安全 C++
【C++航海王:追寻罗杰的编程之路】智能指针
【C++航海王:追寻罗杰的编程之路】智能指针
40 0
|
6月前
|
安全 编译器 程序员
【C++11】智能指针
【C++11】智能指针
32 0
|
2月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
154 13
|
3月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
41 0