ETH官方钱包

前往
大廳
主題

C語言變數(shù)生命週期觀察與Lambda運算式入門

Yang | 2024-01-28 10:59:21 | 巴幣 0 | 人氣 168

接續(xù)以前寫的:
C取時間和指標使用上的一些眉角
C在編譯時帶入的變數(shù)

一般變數(shù)不太容易觀察生命週期,還好class在建立(new)和消滅(delete)時,會呼叫建構(gòu)子(Constructor)和解構(gòu)子(Destructor),在裡面加入log觀察,幫助理解加深記憶

Lambda運算式在C#很常見,但是C的Lambda功能更多也更複雜,

這裡先用來觀察建構(gòu)子和解構(gòu)子,更多的應(yīng)用範例待以後的文章補充

#define STR(N) #N
#define XSTR(N) STR(N)

//__LINE__型態(tài)是%d,利用XSTR轉(zhuǎn)換成%s
#define _LINE_STR_ XSTR(__LINE__)

class MyClass
{
    public:
    MyClass()
    {
        printf("Constructor|%s|%s", _LINE_STR_, __FUNCTION__); //__FUNCTION__=="MyClass"
    }

    public:
    ~MyClass()
    {
        printf("Destructor|%s|%s", _LINE_STR_, __FUNCTION__); //__FUNCTION__=="~MyClass"
    }

    public:
    static MyClass *Factory()
    {
        return new MyClass();
    }
};

int main(const int argc, const char *argv[])
{
    { //_mf0只會活在大括弧內(nèi),離開大括弧時,會觸發(fā)解構(gòu)子
        const MyClass _mf0();
    }

    { //Lambda練習1
        auto lambda = [](void) { return new MyClass(); }; //離開大括弧時,不會觸發(fā)解構(gòu)子

        const MyClass *_mf1 = lambda();

        delete _mf1; //觸發(fā)解構(gòu)子
    }

    { //Lambda練習2
        std::function<MyClass *()> func = MyClass::Factory; //離開大括弧時,不會觸發(fā)解構(gòu)子

        const MyClass *_mf2 = func();

        delete _mf2; //觸發(fā)解構(gòu)子
        delete _mf2; //程式當?shù)?/div>
    }

    return EXIT_SUCCESS;
}

Lambda練習1和練習2推測是等價的語法,觀察執(zhí)行時間都小於1 usec,看不出效能差異

Lambda練習2的彈性更廣,能當作變數(shù)傳遞給別的函式使用

多delete一次就會使程式當?shù)簦瑫蓄愃埔韵碌腻e誤訊息,不同平臺訊息可能不一樣,但程式都會當?shù)簦?/div>
Exception has occurred.
Aborted

double free or corruption (fasttop): 0x0000000000646030 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81299)[0x7ffff7052299]

當?shù)暨@點看來是沒救了,沒找到方法是能讓程式繼續(xù)往下執(zhí)行的

結(jié)論C語言是有借有還的語言,借多少就要還多少,
還少一點(Memory Leak),程式可能可以跑久一點,直到吃光機器的記憶體形成大災(zāi)難,
還多一點,立刻當?shù)魶]得救

20240129補充Lambda練習3,紀錄
1.重複使用指標,忘記釋放記憶體的情況
2.多一層NULL判斷,避免重複delete,但是程式碼會很醜

MyClass *_mcPtr = NULL;

{ //區(qū)塊1
    auto lambda = [](void) { return new MyClass(); };

    _mcPtr = lambda();
}

{ //區(qū)塊2
    std::function<MyClass *()> func = MyClass::Factory;

    _mcPtr = func(); //重複使用指標,忘記釋放區(qū)塊1(Memory Leak)

    //後來發(fā)現(xiàn)以下程式碼是不好的寫法,之後再補充修正
    if (_mcPtr != NULL)
    {
        delete _mcPtr; //觸發(fā)區(qū)塊2解構(gòu)子
    }
    _mcPtr = NULL;
}

if (_mcPtr != NULL) //多一層NULL判斷,避免重複delete
{
    delete _mcPtr; //程式不會當?shù)簦菂^(qū)塊1變成沒用的孤兒記憶體,直到程式結(jié)束
}
_mcPtr = NULL;
送禮物贊助創(chuàng)作者 !
0
留言

創(chuàng)作回應(yīng)

相關(guān)創(chuàng)作

更多創(chuàng)作