智能指針的簡單用法

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;
}

好了,以上都是比較基本的用法,暫且寫這麼多。

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