智能指针的简单用法

std::shared_ptr

首先来介绍shared_ptr,包含在memory头文件中,它的存在,使得更容易也更安全地使用动态内存。

智能指针也是模板,常用其初始化方式有以下几种。初始化方式:

1)默认初始化方式。

std::shared_ptr<std::string> p1;    // 指向空string
std::shared_ptr<std::list<int>> p2; // 指向int的list

2)使用make_shared函数模板,make_shared声明如下:(推荐

template <class T, class... Args>
shared_ptr<T> make_shared (Args&&... args);


从声明可以看出其用法,必须指定想要创建的对象的类型,例如:

// 指向一个值为3的int的shared_ptr
std::shared_ptr<int> p3 = std::make_shared<int>(3);

// 指向值为"9999"的string
std::shared_ptr<std::string> p4 = std::make_shared<std::string>(4, '9');

// 更简洁的方式,使用auto保存返回结果,构造一个指向空vector<std::string>
auto p5 = std::make_shared<std::vector<std::string>>();

表示使用括号内参数来构造给定的类型对象。

3) 结合new,直接初始化形式

std::shared_ptr<int> p2(new int(4));  // 必须显示初始化,不支持隐式转换。

shared_ptr会根据其所指向的对象的引用计数是否为0来决定是否销毁该对象,,并释放所占用的内存。注意不要混合使用普通指针和智能指针,若将一个智能指针绑定到一个普通指针时,我们就把内存的责任交给share_ptr来处理,就不要再使用普通指针来访问内存了。

4) reset方式 

std::shared_ptr<int> sp2;
sp2.reset(new int(3));

std::weak_ptr

std::weak是对对象的弱引用,是一种不控制对象生存期的指针,只是用于访问对象,通俗地说就是当没有shared_ptr之类指针指向对象时,即使有weak_ptr指向对象,对象依然会被释放。

初始化代码示例:

#include <iostream>
#include <memory>


int main ()
{
    // 构建一个shared_ptr
    auto sp = std::make_shared<int>(42);
    std::cout << "sp use count is " << sp.use_count() << std::endl;

    // 方式1 通过构造函数初始化
    std::weak_ptr<int> wp1(sp);
    std::cout << "sp use count is " << sp.use_count() << std::endl;

    // 方式2 通过拷贝构造函数来初始化
    std::weak_ptr<int> wp2(wp1);
    std::cout << "sp use count is " << sp.use_count() << std::endl;

    // 方式3 通过weak_ptr来赋值初始化
    std::weak_ptr<int> wp3;
    wp2 = wp1;
    std::cout << "sp use count is " << sp.use_count() << std::endl;

    // std::weak_ptr 访问对象的方式举例
    if (!wp2.expired())
    {
        if (auto np2 = wp2.lock())
        {
            std::cout << "-----np2 point to value is " << *np2 << std::endl;
        }
    }
    
    sp.reset();
    if (wp2.expired())
    {
        std::cout << "obj has been dectruct." << std::endl;
    }
    else
    {
        if (auto np2 = wp2.lock())
        {
            std::cout << "====np2 point to value is " << *np2 << std::endl;
        }
    }

  return 0;
}

输出信息如下:

sp use count is 1
sp use count is 1
sp use count is 1
sp use count is 1
-----np2 point to value is 42
obj has been dectruct.

std::weak_ptr因为不管理对象的生命周期,所以它一般适用于那些资源对象,能用就用,如果已经销毁了就不用的使用场景。

std::unique_ptr指针

一个unique_ptr “拥有”它所指向的对象,任意时刻只能有一个unique_ptr指针指向一个给定的对象。unique_ptr的初始化方式如下:

#include <iostream>
#include <memory>


int main ()
{
    // 方式1 使用默认构造函数
    std::unique_ptr<double> up1;

    // 方式2 通过内置指针构造
    std::unique_ptr<double> up3(new double(9.9));
    std::cout << "up3 point to value: " << *up3 << std::endl;

    // 方式3 使用reset
    std::unique_ptr<double> up4;
    up4.reset(new double(8.8));
    std::cout << "up4 point to value: " << *up4 << std::endl;

    // 方式4 使用make_unique c++14才支持
    std::unique_ptr<double> up5 = std::make_unique<double>(7.7);
    std::cout << "up5 point to value: " << *up5 << std::endl;

    return 0;
}

release结合reset的unique_ptr的用法

#include <iostream>
#include <memory>


int main ()
{
    std::unique_ptr<int> up1(new int(1));
    std::cout << "up1 point to value: " << *up1 << std::endl;

    // release 放弃对指针的控制权,返回指针并将up1置空
    std::unique_ptr<int> up2(up1.release());
    std::cout << "up2 point to value: " << *up2 << std::endl;


    std::unique_ptr<int> up3(new int(3));
    // 将所有权从up2转移到up3
    up3.reset(up2.release());
    std::cout << "up3 point to value: " << *up3 << std::endl;

    std::unique_ptr<int> up4 = std::make_unique<int>(4);
    //up4.release();             // 错误写法:up4不会释放内存,且丢失了其之前所指向对象的指针
    std::cout << "up4 point to value: " << *up4 << std::endl;
    auto p = up4.release();    // 正确写法:需要记录返回的指针且记得delete p 操作
    delete p;

    std::cout << "hello world" << std::endl;
    return 0;
}

输出信息如下:

up1 point to value: 1
up2 point to value: 1
up3 point to value: 1
up4 point to value: 4
hello world

std::unique_ptr移动构造

#include <iostream>
#include <memory>

// std::unique_ptr 不支持copy 构造和 copy赋值

int main ()
{
    std::unique_ptr<int> up1 = std::make_unique<int>(1);
    std::unique_ptr<int> up2(std::move(up1));

    std::unique_ptr<int> up3;
    up3 = std::move(up2);
    std::cout << "up3 point to value: " << *up3 << std::endl;

    return 0;
}

好了,以上都是比较基本的用法,暂且写这么多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章