• Index

智能指针的简单使用

Reads: 10

智能指针就是为了方便释放堆内存和解决各种需要程序员注意的细节而出现的,智能指针不强制程序员手动释放堆内存。当智能指针离开作用域时,智能指针会自动释放它指向的堆内存。这篇教程将讲解如何简单地使用智能指针。

独占指针

std::unique_ptr是独占指针的类型,独占指针是智能指针的一种,它在memory标准库中。

基础示例

先来看看独占指针的创建和使用:

#include <iostream> // std::cout std::endl std::boolalpha
#include <memory> // std::unique_ptr

int main(void)
{
    // 创建默认的独占指针,默认的独占指针被初始化为nullptr
    std::unique_ptr<int> pointer1;
    std::cout << std::boolalpha << "默认独占指针被初始化为nullptr:" << (pointer1 == nullptr) << std::endl;

    // 申请堆内存并且初始化内存数据为2333, 然后将内存地址赋值给pointer1
    pointer1 = std::make_unique<int>(2333);
    std::cout << *pointer1 << std::endl;

    // 申请堆内存并且初始化内存数据为666, 然后将内存地址初始化给pointer2
    auto pointer2 = std::make_unique<int>(666); 
    std::cout << *pointer2 << std::endl;

    return 0;
}

输出结果:

默认独占指针被初始化为nullptr:true
2333
666

基础讲解

以下是创建默认的独占指针pointer,用来保存int类型的内存地址。默认创建的独占指针会被初始化为指针空值nullptr

std::unique_ptr<int> pointer;

以下这个函数是申请int类型的堆内存并且保存到一个独占指针中,然后返回这个独占指针:

std::make_unique<int>(666);

函数里的参数是函数<>里类型的构造参数,上面的这个函数内部实现的功能类似于new int(666);;当函数不填写参数时,即std::make_unique<int>();,就相当于new int();

以上就是创建独占指针的方法,而使用方法和普通的指针一样。

基础补充

std::unique_ptr声明的指针独占一份堆内存。也就是说,一份堆内存同一时间只能由一个独占指针保存它的地址,其他指针都不能通过赋值来保存这份堆内存的地址;如果想用其他独占指针保存这份堆内存,则只能通过转移来赋值。先看看一个简单的栗子:

#include <iostream> // std::cout std::endl std::boolalpha
#include <memory> // std::unique_ptr

int main(void)
{
    auto pointer1 = std::make_unique<int>(666);
    // auto pointer2 = pointer1; // 赋值操作, 去掉开头注释编译将会报错
    auto pointer2 = std::move(pointer1); // 转移操作
    std::cout << std::boolalpha << (pointer1 == nullptr) << std::endl;
    std::cout << *pointer2 << std::endl;
    return 0;
}

输出结果:

true
666

共享指针

std::shared_ptr是共享指针的类型,共享指针是智能指针的一种,它在memory标准库中。

顾名思义,共享指针保存的内存地址可以共享给其他共享指针。由于它可以共享,为了保证它的安全性,共享指针自身所需内存也比独占指针要多一点,而内部会比独占指针多小小操作,所以性能会有小小下降。共享指针的额外消耗非常小,一般可以忽略;如果系统资源对这些损耗非常敏感,可以考虑尽量使用独占指针。

基础示例

#include <iostream> // std::cout std::endl std::boolalpha
#include <memory> // std::shared_ptr

int main(void)
{
    // 创建默认的共享指针,默认的共享指针被初始化为nullptr
    std::shared_ptr<int> pointer1;
    std::cout << std::boolalpha;
    std::cout << "默认共享指针被初始化为nullptr:" << (pointer1 == nullptr) << std::endl;

    // 申请堆内存并且初始化内存数据为2333, 然后将内存地址赋值给pointer1
    pointer1 = std::make_shared<int>(2333);
    std::cout << "pointer1指向的内存的值:" << *pointer1 << std::endl << std::endl;

    // pointer1赋值给pointer2
    auto pointer2 = pointer1;
    std::cout << "pointer2保存的地址是否等于pointer1保存的地址:" << (pointer1 == pointer2) << std::endl;
    std::cout << "pointer2指向的内存的值:" << *pointer2 << std::endl << std::endl;

    // pointer1保存的内存地址转移给pointer3
    auto pointer3 = std::move(pointer1); // 
    std::cout << "转移后pointer1是否保存指针空值:" << (pointer1 == nullptr) << std::endl;
    std::cout << "pointer2保存的地址是否等于pointer3保存的地址:" << (pointer2 == pointer3) << std::endl;
    std::cout << "pointer2指向的内存的值:" << *pointer2 << std::endl;
    std::cout << "pointer3指向的内存的值:" << *pointer3 << std::endl;

    return 0;
}

输出结果:

默认共享指针被初始化为nullptr:true
pointer1指向的内存的值:2333

pointer2保存的地址是否等于pointer1保存的地址:true
pointer2指向的内存的值:2333

转移后pointer1是否保存指针空值:true
pointer2保存的地址是否等于pointer3保存的地址:true
pointer2指向的内存的值:2333
pointer3指向的内存的值:2333

基础讲解

共享指针的操作和独占指针的操作类似,使用函数std::make_shared申请内存并返回一个共享指针。而共享指针可以把它保存的地址共享给其他共享指针,独占指针则不行。

补充知识

  1. 智能指针从C++11开始加入。
  2. 函数std::make_unique()从C++14开始加入。

Comments

Make a comment

  • Index

WARNING: You are using an old browser that does not support HTML5. Please choose a modern browser (Chrome / Microsoft Edge / Firefox / Sarafi) to get a good experience.