c++命名對象和匿名對象的解析

最近在看muduo庫,對裡面的日志庫比較感興趣,於是看到瞭以下的語句:

 剛看到這些語句時,和平時遇到日志打印的語句不太一樣,很疑惑這樣一條語句是怎麼把日志打印出來的。網上搜索一翻後,學到瞭一個知識點:匿名對象。其實在平時的編碼中我們也經常會遇到匿名對象,隻是沒有關註。簡單的一個匿名對象如:

std::string anonymous = std::string(“anonymous”);

像按值傳遞的對象(函數入參,函數返回值)都是匿名對象,那匿名對象的特點是什麼呢?通過下面一段代碼可知:

#ifndef __CLOGER_H__
#define __CLOGER_H__
 
#include <string>
#include <stdlib.h>
#include <stdio.h>
 
class CLoger
{
public:
    explicit CLoger(std::string &str): mStr(str)
    {
 
    }
 
    ~CLoger()
    {
        printf("destructor mStr = %s\n", mStr.c_str());
    }
 
    std::string &string()
    {
        return mStr;
    }
private:
    std::string mStr;
};
 
#endif
 
#include "anonymous_object.h"
int main()
{
    std::string name("name");
    CLoger loger(name); //具名對象,main函數退出後才會銷毀
 
    std::string anonymous("anonymous");
    CLoger(anonymous).string(); //匿名對象,使用完即銷毀,即此語句結束後立即調用其析構函數
    printf("main finish!\n");
    return 0;
}

運行結果如下:

1,命名對象(非new)在離開作用域後,調用析構函數。

2,匿名對象在離開定義它的語句後,調用析構函數。

瞭解匿名對象的特點後,回到上面的日志打印語句,如其中一條語句:

#define LOG_TRACE if (CLogger::logLevel() <= CLogger::TRACE) \

  CLogger(__FILE__, __LINE__, CLogger::TRACE, __func__).stream()

定義瞭一個匿名對象CLogger,在調用完這條語句後,調用其析構函數:

CLogger::~CLogger()
{
    mImpl.finish();  //打印結尾添加文件名和行號
    const CLogStream::Buffer& buf(stream().buffer());
    g_output(buf.data(), buf.length()); //函數指針調用,默認是輸出到標準輸出stdout,這裡是日志最終輸出的語句
 
    if (mImpl.mLevel == FATAL)
    {
        g_flush();
        abort();
    }
}

 所以,隻要調用語句如LOG_INFO:

int main(int argc, char* argv[])
{  
    char name[256];
    strncpy(name, argv[0], 256);
    CAsyncLogging log(::basename(name), kRollSize);
    log.start();
    g_asyncLog = &log;
 
    bool longLog = argc > 1;
    // bench(longLog);
    LOG_INFO << "loggingTest!";
 
    return 0;
}

這個日志庫已經被我抽離出來,可以單獨編譯一個日志庫,有興趣的同學可以到git下載。

到此這篇關於c++命名對象和匿名對象的解析的文章就介紹到這瞭,更多相關c++命名對象和匿名對象內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: