这是“作用域锁定”惯用语的示例,有一个常见错误:没有创建局部变量,因此锁定无效。这段代码可以在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/

    10-11 16:53