天天看點

【足迹C++primer】39、動态記憶體與智能指針(3)

動态記憶體與智能指針(3)

/**
* 功能:動态記憶體與智能指針
* 時間:2014年7月8日15:33:58
* 作者:cutter_point
*/


#include<iostream>
#include<vector>
#include<memory>
#include<string>

using namespace std;
/**
智能指針和異常
*/
void f()
{
    shared_ptr<int> sp(new int(42));        //配置設定一個新對象
    //這段代碼抛出一個異常,且在f中未被捕獲
}//在函數結束時shared_ptr自動釋放記憶體

/*
函數退出有兩種可能,正常處理結束或者發生了異常,無論哪種情況,局部對象都會被銷毀
*/

//當發生異常的時候,我們直接管理的記憶體是不會直接釋放的
void fun1()
{
    int *ip=new int(42);        //動态配置設定一個新對象
    //這段代碼抛出一個異常,且在fun1中未被捕獲
    delete ip;      //在退出之前釋放記憶體
}

/**
智能指針和啞類
*/
struct destination{};     //表示我們正在連接配接什麼;
struct connection{};      //使用連接配接所需的資訊;
connection connect(destination*){}   //打開連接配接
void disconnect(connection){}        //關閉給定的連結
void f(destination &d/* 其他參數 */)
{
    //獲得一個連結;記住使用完後要關閉它
    connection c=connect(&d);
    //使用連接配接
    //如果我們在f退出前忘記調用disconnect,就無法關閉c了
}

/**
使用我們自己的釋放操作
*/
void end_connection(connection *p){disconnect(*p);}

void fun2(destination &d/* 其他參數 */)
{
    connection c=connect(&d);
    shared_ptr<connection> p(&c, end_connection);
    //使用連接配接
    //當fun2退出的時候(即使是由于異常退出),connection會被正确關閉
}

/**
unique_ptr
*/
//初始化unique_ptr必須采用直接初始化形式
//由于一個unique_ptr擁有它指向的對象,是以unique_ptr不支援普通的拷貝或指派操作
void fun3()
{
    unique_ptr<string> p1(new string("Stegosaurus"));
//    unique_ptr<string> p2(p1);  //錯誤:unique_ptr不支援拷貝
    unique_ptr<string> p3;
//    p3=p2;                      //錯誤:unique_ptr不支援指派
}

void fun4()
{
    unique_ptr<string> p1(new string("Stegosaurus"));
//    unique_ptr<string> p2(p1);  //錯誤:unique_ptr不支援拷貝
//    unique_ptr<string> p3;
//    p3=p2;                      //錯誤:unique_ptr不支援指派
    //将所有權從p1(指向string Stegosaurus)轉移給p2

    unique_ptr<string> p2(p1.release());    //release将p1置為空
    unique_ptr<string> p3(new string("Text"));
    //将所有權從p3轉移到p2
    p2.reset(p3.release()); //reset釋放了p2原來指向的記憶體
}

/**
傳遞unique_ptr參數和傳回unique_ptr
*/
//傳回一個unique_ptr
unique_ptr<int> clone(int p)
{
    //正确:從int*建立一個unique_ptr<int>
    return unique_ptr<int>(new int(p));
}

//傳回一個局部對象拷貝
unique_ptr<int> fun5(int p)
{
    unique_ptr<int> ret(new int(p));
    //...
    return ret;
}

/**
向unique_ptr傳遞删除器
*/

/*
void fun6()
{
    //p指向一個類型為objT的對象,并使用一個類型為delT的對象釋放objT對象
    //他會調用一個fcn的delT類型對象
    using objT=int;
    using delT=int;
    delT fcn;
    unique_ptr<objT, delT> p(new objT,fcn);
}
有問題!!!!應該用lambda
*/


/*
void fun7(destination &d /* 其他參數//* )
{
    connection *pc;
    connection c=connect(&d);       //打開連接配接
    //當p被銷毀時候,連接配接将會關閉
    unique_ptr<connection, decltype(end_connection)*)
    p(&c, end_connection);
    //使用連接配接
    //當fun7退出時,即使是異常退出,連接配接也會正常關閉
}
*/
/**
weak_ptr
*/
//weak_ptr是一種不控制所指向對象生存期的智能指針,它指向一個shared_ptr
//管理的對象
//當我們建立一個weak_ptr時,要用一個shared_ptr來初始化它
void fun8()
{
    auto p=make_shared<int>(42);
    weak_ptr<int> wp(p);    //wp弱共享p;p的引用計數未改變
/*
由于對象可能不存在,我們不能使用weak_ptr直接通路對象,而必須調用lock.
lock傳回一個指向共享對象的shared_ptr.
*/
    if(shared_ptr<int> np=wp.lock())
    {
        //如果np不為空則條件成立
        //if中,np與p共享對象
    }
}

/**
核查指針類
*/
/*
通過使用weak_ptr,不會影響一個給定的StrBlob所指向的vector的生存期。
但是,可以阻止使用者通路一個不再存在的vector的企圖
*/
//對于通路一個不存在的元素的嘗試,StrBlobPtr抛出一個異常
class StrBlobPtr
{
public:
    StrBlobPtr():curr(0) {}
    StrBlobPtr(StrBlob &a, size_t sz=0):wptr(a.data),curr(sz){}
    string& deref() const;
    StrBlobPtr &incr();     //字首遞增
private:
    //若檢查成功,check傳回一個指向vector的shared_ptr
    shared_ptr<vector<string>> check(size_t, const string&) const;
    //儲存一個weak_ptr, 意味着底層vector可能會被銷毀
    weak_ptr<vector<string>> wptr;
    size_t curr;    //在數組中的目前位置
};


int main()
{

    return 0;
}
           

PS:不要問我,為什麼要這樣寫,因為我基本吧要寫的都寫到裡面去了,可以看出我是先打好草稿再往上傳的,但是有個問題這節确實是有點亂,好多我搞半天就是實作不了,上網查别人也是這樣寫,但我就是不能搞出來,我不知道是哪根筋沒跳對- -,總之先看過再說,以後回頭再看的時候應該會知道吧,其實作在看到從前寫的那些覺得比較難的,現在看來似乎沒那麼難了,基本現在很輕松就可以搞出來,我是不是有點小進步呢!!

【足迹C++primer】39、動态記憶體與智能指針(3)

繼續閱讀