Why garbage collection when RAII is available?

前端 未结 7 1287
深忆病人
深忆病人 2021-02-01 14:00

I hear talks of C++14 introducing a garbage collector in the C++ standard library itself. What is the rationale behind this feature? Isn\'t this the reason that RAII exists in

7条回答
  •  盖世英雄少女心
    2021-02-01 14:06

    Definitions:

    RCB GC: Reference-Counting Based GC.

    MSB GC: Mark-Sweep Based GC.

    Quick Answer:

    MSB GC should be added into the C++ standard, because it is more handy than RCB GC in certain cases.

    Two illustrative examples:

    Consider a global buffer whose initial size is small, and any thread can dynamically enlarge its size and keep the old contents accessible for other threads.

    Implementation 1 (MSB GC Version):

    int*   g_buf = 0;
    size_t g_current_buf_size = 1024;
    
    void InitializeGlobalBuffer()
    {
        g_buf = gcnew int[g_current_buf_size];
    }
    
    int GetValueFromGlobalBuffer(size_t index)
    {
        return g_buf[index];
    }
    
    void EnlargeGlobalBufferSize(size_t new_size)
    {
        if (new_size > g_current_buf_size)
        {
            auto tmp_buf = gcnew int[new_size];
            memcpy(tmp_buf, g_buf, g_current_buf_size * sizeof(int));       
            std::swap(tmp_buf, g_buf); 
        }   
    }
    

    Implementation 2 (RCB GC Version):

    std::shared_ptr g_buf;
    size_t g_current_buf_size = 1024;
    
    std::shared_ptr NewBuffer(size_t size)
    {
        return std::shared_ptr(new int[size], []( int *p ) { delete[] p; });
    }
    
    void InitializeGlobalBuffer()
    {
        g_buf = NewBuffer(g_current_buf_size);
    }
    
    int GetValueFromGlobalBuffer(size_t index)
    {
        return g_buf[index];
    }
    
    void EnlargeGlobalBufferSize(size_t new_size)
    {
        if (new_size > g_current_buf_size)
        {
            auto tmp_buf = NewBuffer(new_size);
            memcpy(tmp_buf, g_buf, g_current_buf_size * sizeof(int));       
            std::swap(tmp_buf, g_buf); 
    
            //
            // Now tmp_buf owns the old g_buf, when tmp_buf is destructed,
            // the old g_buf will also be deleted. 
            //      
        }   
    }
    

    PLEASE NOTE:

    After calling std::swap(tmp_buf, g_buf);, tmp_buf owns the old g_buf. When tmp_buf is destructed, the old g_buf will also be deleted.

    If another thread is calling GetValueFromGlobalBuffer(index); to fetch the value from the old g_buf, then A Race Hazard Will Occur!!!

    So, though implementation 2 looks as elegant as implementation 1, it doesn't work!

    If we want to make implementation 2 work correctly, we must add some kind of lock-mechanism; then it will be not only slower, but less elegant than implementaion 1.

    Conclusion:

    It is good to take MSB GC into the C++ standard as an optional feature.

提交回复
热议问题