2017-04-13 66 views
0

工作情況:爲什麼我們可以鎖定一個const對象中定義的互斥鎖?

template<typename T> 
class threadsafe_queue 
{ 
private: 
    mutable std::mutex mut; 
    std::queue<T> data_queue; 

public: 
    threadsafe_queue() 
    {} 

    threadsafe_queue(const threadsafe_queue& other) 
    { 
     std::lock_guard<std::mutex> lk(other.mut); 
     data_queue=other.data_queue; 
    } 
}; 

情況下應該會失敗:注意沒有mutablestd::mutex mut;

template<typename T> 
class threadsafe_queue 
{ 
private: 
    std::mutex mut; 
    std::queue<T> data_queue; 

public: 
    threadsafe_queue() 
    {} 

    threadsafe_queue(const threadsafe_queue& other) 
    { 
     std::lock_guard<std::mutex> lk(other.mut); 
     data_queue=other.data_queue; 
    } 
}; 

我曾嘗試上面列出的這兩種情況下,他們編譯沒有問題。我在內部假設lock_guard調用mutex :: lock函數,它本身不是一個const函數。

問題>爲什麼我們可以在複製構造函數中鎖定const對象的互斥量?

+1

肯定'可變'是這裏的關鍵? –

+0

@OliverCharlesworth:看看第二個版本,'mutable'關鍵字消失了。提問者報告說該版本也起作用。 – user2357112

+0

@ user2357112 - 它並不真正工作,雖然:http://ideone.com/2MVs0O –

回答

6

第一個示例編譯,因爲該互斥體被限定爲mutable。這意味着這個字段可以被修改,變異,而不包含被認爲已經被改變的包含對象。所以,從某種意義上講,互斥體的狀態不是「隊列的一部分」。編譯器允許const方法修改mutable成員。

僅當您沒有實際嘗試實例化該類並使用該方法時,該示例纔會編譯。如果你這樣做,it fails。模板是神奇的...

+0

看看第二個版本,'mutable'關鍵字不見了。提問者報告說該版本也起作用。 – user2357112

+0

@ user2357112:謝謝,請參閱編輯。 – einpoklum

+1

第二個是形成不良的程序,因爲如果模板函數是合法的,沒有'T'允許實例化。但是,不需要診斷,因此編譯器可以自由編譯並忽略它。我相信這個規則的存在是爲了允許但不要求編譯器產生額外的診斷。這一規則的實際影響從字面上解釋是荒謬的,因爲該標準規定不對形成惡劣程序的行爲加以限制...... – Yakk