简体   繁体   English

使用临时实例的const正确性

[英]Const correctness with temporary instances

Here is the example of the "scoped lock" idiom with common mistake: no local variable is created, so lock is not in effect. 以下是具有常见错误的“范围锁定”习惯用法的示例:未创建局部变量,因此锁定无效。 This code compiles flawlessly both with VC++ 2010 and Comeau C++ online: 这段代码在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();
}

If default constructor for ScopedLock is commented out, then both compilers give an error: 如果注释掉ScopedLock的默认构造函数,则两个编译器都会给出错误:

error C2512: 'ScopedLock' : no appropriate default constructor available 错误C2512:'ScopedLock':没有合适的默认构造函数可用

(When ScopedLock used correctly, ie local variable is created: ScopedLock guard(m_mutex); , then compilation fails as expected. Declaring m_mutex as mutable fixes the problem.) (当ScopedLock正确使用时,即创建局部变量: ScopedLock guard(m_mutex);然后编译按预期失败。将m_mutex声明为可变修复问题。)

I have two questions: 我有两个问题:

  1. Why X::foo compiles? 为什么X::foo编译? It seems that compiler was able to cast const Mutex& to Mutex& somehow. 似乎编译器能够以某种方式将const Mutex& Mutex&Mutex&

  2. What role plays ScopedLock default constructor, so the compilation succeeds? 扮演ScopedLock默认构造函数的角色是什么,所以编译成功了?

Thanks. 谢谢。

Update: I found the answer. 更新:我找到了答案。 It appears that ScopedLock(m_mutex); 看来是ScopedLock(m_mutex); statement creates a local variable m_mutex of type ScopedLock . statement创建一个m_mutex类型的局部变量ScopedLock Not a temporary. 不是暂时的。 That's why ScopedLock::ScopedLock default constructor is required. 这就是为什么ScopedLock::ScopedLock默认构造函数是必需的。

You answered the question yourself. 你自己回答了这个问题。

It appears that ScopedLock(m_mutex); 看来是ScopedLock(m_mutex); statement creates a local variable m_mutex of type ScopedLock statement创建一个ScopedLock类型的局部变量m_mutex

The explanation is to be found in the Standard's Section 6.8 Ambiguity Resolution: 解释可在标准的6.8节歧义解决方案中找到:

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion [5.2.3] as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration . 在涉及表达式语句和声明的语法中存在歧义:具有函数式显式类型转换[5.2.3]的表达式语句,因为其最左侧的子表达式与第一个声明符以(a)开头的声明无法区分。 在这些情况下,该声明是一个声明

The Standard then lists T(a); 标准然后列出T(a); as an example of a statement that is really a declaration. 作为一个真正声明的声明的例子。 It is equivalent to T a; 它相当于T a;

This is one variation of the infamous C++ "most vexing parse". 这是臭名昭着的C ++“最令人烦恼的解析”的一种变体。

I'm pretty sure your problem is line 26: ScopedLock(m_mutex); 我很确定你的问题是第26行: ScopedLock(m_mutex);

Instead, that should be something like ScopedLock a_variable_name(m_mutex); 相反,它应该类似于ScopedLock a_variable_name(m_mutex);

When I make that change, I get the expected errors: 当我做出改变时,我得到了预期的错误:

constCorrectness.cpp: In member function ‘void X::foo() const’:
constCorrectness.cpp:26: error: no matching function for call to ‘ScopedLock::ScopedLock(const Mutex&)’
constCorrectness.cpp:18: note: candidates are: ScopedLock::ScopedLock(const ScopedLock&)
constCorrectness.cpp:11: note:                 ScopedLock::ScopedLock(Mutex&)
constCorrectness.cpp:10: note:                 ScopedLock::ScopedLock()

Perhaps somebody can interpret ScopedLock(m_mutex) for us? 也许有人可以为我们解释 ScopedLock(m_mutex) Does it declare a function or something? 它是否声明了某个功能? Instead of calling a constructor as expected by the questioner? 而不是像提问者那样调用构造函数? Update: Striking this out. 更新:解决这个问题。 I think it's just a variable declaration (ie the brackets are ignored.) 我认为这只是一个变量声明(即括号被忽略。)

The problem is that the X::foo() method is declared as const - that means that it will not mutate (change) the object. 问题是X :: foo()方法被声明为const - 这意味着它不会改变(改变)对象。

The ScopedLock() constructor doesn't have a overload that accepts a immutable (const) reference to a Mutex object. ScopedLock()构造函数没有接受对Mutex对象的不可变(const)引用的重载。

Fixing this requires you declare m_mutex as mutable, or provide an appropriate overloaded ScopedLock() constructor. 修复此问题需要将m_mutex声明为可变,或者提供适当的重载ScopedLock()构造函数。 I'm thinking the former is preferable. 我认为前者更可取。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM