2017-04-13 16 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

相关问题