【C++11新特性】智能指针

前言

程序中使用new从堆(自由存储区)分配内存,等不再需要时,使用delete将其释放,C++引入智能指针auto_ptr,以帮助自动完成该过程。随后的编程体验中往往需要有更精致的机制,基于程序员的编程体验和BOOST库提供的解决方案,C++摒弃了auto_ptr,新增了三种智能指针:unique_ptr、shared_ptr和weak_ptr。

目录

智能指针

unique_ptr

unique_ptr的创建

unique_ptr成员函数

示例

shared_ptr

shared_ptr的创建

shared_ptr成员函数

示例

weak_ptr

weak_ptr的创建

weak_ptr成员函数

示例

参考文献

智能指针

必须包含头文件

unique_ptr 两个unique_ptr不能指向同一个对象;

shared_ptr 允许多个shared_ptr实例指向同一个对象,通过计数管理;

weak_ptr 辅助类,是一种弱引用,指向shared_ptr所管理的对象。

unique_ptr

unique_ptr不共享它所管理的对象(两个unique_ptr不能指向同一个对象),只能移动unique_ptr,即对资源管理权限可以实现转移。这意味着,内存资源所有权可以转移到另一个unique_ptr,并且原始unique_ptr不再拥有此资源。

unique_ptr的创建

创建方式:unique_ptr  T为指针所指数据类型

// 初始化方式1
unique_ptr p1(new string("Ladies and Gentlemen!!"));
// 初始化方式2
unique_ptr p2;
p2.reset(new string("Magic show to start!!"));

[注]C++11中没有make_unique,C++14才有

unique_ptr成员函数

成员函数名 功能
operator*() 获取当前unique_ptr指针指向的数据。
operator->() 重载->号,当智能指针指向的数据类型为自定义的结构体时,通过->运算符可以获取其内部的指定成员。
operator =() 重载了 = 赋值号,从而可以将nullptr或者一个右值unique_ptr指针直接赋值给当前同类型的unique_ptr指针。
operator []() 重载了 [] 算符,当unique_ptr指针指向了一个数组,可以直接通过 [] 获取指定下标位置处的数据。
get() 获取当前unique_ptr指针内部包含的普通指针。
get_delecter() 获取当前unique_ptr指针释放堆内存空间所用的规则。
operator bool() unique_ptr指针可直接作为if语句的判断条件,以判断该指针是否为空,如果为空,则为flase;反之为true。
relase() 释放当前unique_ptr指针对所指堆内存的所有权,但该存储空间不会被销毁。
reset(p) 其中p表示一个普通指针,如果p为nullptr,则当前unique_ptr也变为空指针;反之,则该函数会释放当前unique_ptr指针指向的堆内存(如果有),然后获取p所指堆内存的所有权(p为nullptr)。

swap(x)

交换当前unique_ptr指针和同类型的x指针。

示例

#include 
#include 
#include 

using namespace std;

int main()
{
    unique_ptr p1(new string);
    *p1 = "Ladies and Gentlemen!Magic show to start!";
    // p接受p1释放的堆内存
    string *p = p1.release();
    cout << *p << endl;
    // 判断p1是否为空指针
    if (p1){
        cout << "p1 is not nullptr" << endl;

    }
    else {
        cout << "p1 is nullptr" << endl;
    }
    unique_ptr  p2;
    p2.reset(p);
    cout << *p2 << endl;
    return 0;
}

程序执行结果:

Ladies and Gentlemen!Magic show to start!
p1 is nullptr
Ladies and Gentlemen!Magic show to start!

shared_ptr

允许多个指针指向同一个对象,利用计数的方式实现对所管理的对象的所有权分享,即允许多个shared_ptr共同管理一个对象。

shared_ptr的创建

推荐第一次创建内存资源时,使用make_shared函数创建shared_ptr。

// 初始化方式1
auto p1 = make_shared("Ladies and Gentlemen!");
// 初始化方式2
shared_ptr p2(new string("Magic show to start!"));
// 初始化方式3
shared_ptr p3(nullptr);
p3 = make_shared("It's show time!");

shared_ptr成员函数

成员函数名 功能
operator*() 获取当前shared_ptr智能指针对象指向的数据。
operator->() 重载->号,当智能指针指向的数据类型为自定义的结构体时,通过->运算符可以获取其内部的指定成员。
operator=() 重载 = 赋值号,使得同一类型的shared_ptr智能指针可以相互赋值。
get() 获取shared_ptr对象内部包含的普通指针。
use_count() 返回同当前shared_ptr对象(包括它)指向相同的所有shared_ptr对象数量。
unique() 判断当前shared_ptr对象指向的堆内存,是否不再有其他shared_ptr对象指向它。
operator bool() 判断当前shared_ptr对象是否为空智能指针,如果是空指针,返回flase;反之,返回true。
reset() 当函数没有实参时,该函数会使当前shared_ptr所指堆内存的引用计数减1,同时将当前对象重置为一个空指针;当为函数传递一个新申请的堆内存时,则调用该函数的shared_ptr对象会获得该存储空间的所有权,并且引用计数的初始值为1。
swap() 交换2个相同类型shared_ptr智能指针的内容

除此之外,C++11标准还支持同一类型的shared_ptr对象,或者shared_ptr和nullptr之间,进行==,!=,<,<=,>,>= 运算。

示例

#include 
#include 
#include

int main()
{
    // 构建2个指针
    auto p1 = make_shared("Ladies and Gentlemen!It's show time!");
    shared_ptr  p2(p1);
    // 输出p2指向的数据
    cout << *p2 << endl;
    // 引用计数减1,p1为空指针
    p1.reset();
    // 判断p1是否为空指针
    if (p1){
        cout << "p1 is not nullptr" << endl;
    }
    else {
        cout << "p1 is nullptr" << endl;
    }
    // 以上对p1的操作不会影响p2
    cout << *p2 << endl;
    // 查看当前与p2同指向的智能指针个数(包括p2)
    cout << p2.use_count() << endl;

    return 0;
}

程序执行结果:

Ladies and Gentlemen!It's show time!
p1 is nullptr
Ladies and Gentlemen!It's show time!
1

weak_ptr

只与shared_ptr指针搭配使用,借助weak_ptr指针,可以获取shared_ptr指针的一些状态信息,如有多少指向相同的shared_ptr指针,shared_ptr指针指向的堆内存是否已被释放等。

通过使用weak_ptr指针,可以创建一个联接到现有相关实例集的shared_ptr,但前提是基础内存资源仍然有效。weak_ptr本身不参与引用计数,因此,它无法阻止引用计数变为0。但是,可以使用weak_ptr尝试获取初始化该副本的shared_ptr的新副本。若已删除内存,则weak_ptr的bool运算符返回false。若内存仍然有效,则新的共享指针会递增引用计数,并保证只要shared_ptr保留再作用域内,内存就会有效。

weak_ptr的创建

// 初始化方式1 创建一个空指针
weak_ptr p1;
// 初始化方式2 凭借已有的weak_ptr指针,创建一个新的
// 若p1为空指针,则p2也为空指针;
// 若p1指向某一shared_ptr指针拥有的堆内存,则p2也指向该内存空间(可访问,但无所有权)
weak_ptr p2(p1);
// 初始化方式3 指向某一shared_ptr指针拥有的堆内存
shared_ptr p(new int);
weak_ptr p3(p);

weak_ptr成员函数

成员函数名 功能
operator=() 重载 = 赋值运算符,weak_ptr指针可以直接被weak_ptr或者shared_ptr类型指针赋值。
swap(x) 其中x表示一个同类型的weak_ptr类型指针,该函数可以互换2个共同类型weak_ptr指针的内容。
reset() 将当前weak_ptr指针置为空指针。
use_count() 查看指向和当前weak_ptr指针相同的shared_ptr指针的数量。
expired() 判断当前weak_ptr指针是否过期(指针为空,或者指向的堆内存已经被释放)。
lock() 如果当前weak_ptr已经过期,则该函数会返回一个空的shared_ptr指针;反之,该函数返回一个和当前weak_ptr指针指向相同的shared_ptr指针。

值得注意的是,weak_ptr类型指针只能访问某一shared_ptr指针指向的堆内存空间,无法对其进行修改。

示例

#include 
#include 
#include

int main()
{
    shared_ptr sp1(new int(10));
    shared_ptr sp2(sp1);
    weak_ptr wp(sp2);
    // 输出和wp指针指向相同的shared_ptr类型指针数量
    cout << wp.use_count() << endl;
    // 释放sp2
    sp2.reset();
    cout << wp.use_count() << endl;
    // 借助lock()函数,返回一个和wp同指向的share_ptr类型指针,获取其存储的数据
    cout << *(wp.lock()) << endl;

    return 0;
}

程序执行结果:

2
1
10

参考文献

[1]Prata,S.著;张海龙,袁国忠译.C++ Primer Plus中文版:第6版[M].北京:人民邮电出版社,2012.7

[2]智能指针(现代 C++) | Microsoft Docs

[3](11条消息) C++ STL 四种智能指针_恋喵大鲤鱼的博客-CSDN博客_智能指针

[4]如何:创建和使用 unique_ptr 实例 | Microsoft Docs

[5](11条消息) c++11 unique_ptr 与 make_unique源码剖析_私房菜的博客-CSDN博客_make_unique 头文件

[6]C++11 unique_ptr智能指针详解 (biancheng.net)

[7](11条消息) c++11 shared_ptr 与 make_shared源码剖析_私房菜的博客-CSDN博客_make_shared头文件

[8]C++11 shared_ptr智能指针(超级详细) (biancheng.net)

你可能感兴趣的:(C++11新特性,c++)