使用临时实例的const正确性

Ale*_*man 6 c++

以下是具有常见错误的"范围锁定"习惯用法的示例:未创建局部变量,因此锁定无效.这段代码在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();
}
Run Code Online (Sandbox Code Playgroud)

如果注释掉ScopedLock的默认构造函数,则两个编译器都会给出错误:

错误C2512:'ScopedLock':没有合适的默认构造函数可用

(ScopedLock正确使用时,即创建局部变量:ScopedLock guard(m_mutex);,然后编译按预期失败.声明m_mutex为可变修复问题.)

我有两个问题:

  1. 为什么X::foo编译?似乎编译器能够const Mutex&Mutex&某种方式进行转换.

  2. 什么角色扮演ScopedLock默认构造函数,所以编译成功了?

谢谢.

更新:我找到了答案.看来该ScopedLock(m_mutex);语句创建了一个m_mutex类型的局部变量ScopedLock.不是暂时的.这就是为什么ScopedLock::ScopedLock需要默认构造函数的原因.

dec*_*ype 4

你自己回答了这个问题。

看来 ScopedLock(m_mutex); 语句创建一个 ScopedLock 类型的局部变量 m_mutex

解释可以在标准的第 6.8 节歧义解决中找到:

涉及表达式语句和声明的语法存在歧义:以函数样式显式类型转换 [5.2.3] 作为其最左侧子表达式的表达式语句与第一个声明符以 ( 开头的声明无法区分。在这些情况下,声明就是声明

该标准随后列出了T(a);一个实际上是声明的声明示例。它相当于T a;

这是臭名昭著的 C++“最令人烦恼的解析”的一种变体。