[英]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: 我有两个问题:
Why X::foo
compiles? 为什么
X::foo
编译? It seems that compiler was able to cast const Mutex&
to Mutex&
somehow. 似乎编译器能够以某种方式将
const Mutex&
Mutex&
为Mutex&
。
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.