这是“作用域锁定”惯用语的示例,有一个常见错误:没有创建局部变量,因此锁定无效。这段代码可以在VC++ 2010和Comeau C++上完美地编译:
class Mutex
{
public:
void lock() {}
};
class ScopedLock
{
public:
ScopedLock() : m_pm(0) {}
ScopedLock(Mutex& m) : m_pm(&m) { m_pm->lock(); }
private:
Mutex* m_pm;
private:
ScopedLock& operator =(const ScopedLock&);
ScopedLock(const ScopedLock&);
};
class X
{
public:
void foo() const
{
ScopedLock(m_mutex);
}
private:
Mutex m_mutex;
};
int main()
{
X x1;
x1.foo();
}
如果ScopedLock的默认构造函数被注释掉,则两个编译器都将给出错误:
(正确使用
ScopedLock
时,即创建了本地变量:ScopedLock guard(m_mutex);
,然后编译按预期失败。将m_mutex
声明为mutable可以解决此问题。)我有两个问题:
X::foo
可以编译?似乎编译器能够以某种方式将const Mutex&
转换为Mutex&
。 ScopedLock
默认构造函数的角色是什么,所以编译成功? 谢谢。
更新:我找到了答案。看来
ScopedLock(m_mutex);
语句创建了类型为m_mutex
的局部变量ScopedLock
。不是临时的。这就是为什么需要ScopedLock::ScopedLock
默认构造函数的原因。 最佳答案
您自己回答了这个问题。
可以在标准的第6.8节“模糊度解决方案”中找到相应的说明:
然后,标准将T(a);
列出为实际上是声明的语句的示例。相当于T a;
这是臭名昭著的C++“最令人头疼的解析”的一种变体。
关于c++ - 临时实例的正确性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6052857/