临时实例的常量正确性
Const correctness with temporary instances
这是"作用域锁"习惯用法的示例,其中包含常见错误:没有创建局部变量,因此锁无效。这段代码在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 的默认构造函数被注释掉,则两个编译器都会给出错误:
错误 C2512:"作用域锁定":没有可用的适当默认构造函数
(当正确使用ScopedLock
时,即创建局部变量:ScopedLock guard(m_mutex);
,则编译按预期失败。将m_mutex
声明为可变可解决此问题。
我有两个问题:
为什么要
X::foo
编译?编译器似乎能够以某种方式将const Mutex&
转换为Mutex&
。默认构造函数
ScopedLock
什么角色,因此编译成功?
谢谢。
更新:我找到了答案。似乎ScopedLock(m_mutex);
语句创建了一个类型为 ScopedLock
的局部变量m_mutex
。不是临时的。这就是为什么需要ScopedLock::ScopedLock
默认构造函数的原因。
你自己回答了这个问题。
似乎 ScopedLock(m_mutex); 语句创建了一个 ScopedLock 类型的局部变量m_mutex
解释可以在标准的第6.8节歧义解决方案中找到:
涉及表达式语句和声明的语法中存在歧义:将函数样式显式类型转换 [5.2.3] 作为其最左侧子表达式的表达式语句与第一个声明符以 (.在这些情况下,声明是声明。
然后,标准将T(a);
列为真正声明的声明的示例。它相当于T a;
这是臭名昭著的C++"最令人烦恼的解析"的一种变体。
确定你的问题是第 26 行:ScopedLock(m_mutex);
相反,这应该是类似ScopedLock a_variable_name(m_mutex);
当我进行该更改时,我收到预期的错误:
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()
也许有人可以为我们解释更新:删除这个。我认为这只是一个变量声明(即括号被忽略。 ScopedLock(m_mutex)
?它是否声明了一个函数或其他东西?而不是像提问者期望的那样调用构造函数?
问题是 X::foo() 方法被声明为 const - 这意味着它不会改变(更改)对象。
构造函数没有接受对互斥对象的不可变(const)引用的重载。
解决此问题需要将m_mutex声明为可变的,或者提供适当的重载 ScopedLock() 构造函数。 我认为前者更可取。
- 代理对象的常量正确性
- std::函数常量正确性未遵循
- C++ 常量正确性/缺少支持常量和非常量实例的类的常量构造函数
- 自定义引用包装器的常量正确性
- 如果我公开常量和非常量 API,我是否破坏了常量正确性?
- 如何强制实施有关指针数据成员的常量正确性
- 如何在C++的多维地图中实现常量正确性
- C++ 函数参数或声明中的常量正确性
- 结构初始化中的常量正确性
- 常量正确性编译错误到模板函数中的无效转换错误
- 如何在不违反常量正确性的情况下使用 std::lock_guard
- 非平凡变量的常量正确性
- 常量正确性和成员参考
- 常量正确性和shared_ptr,一个设计问题
- 观察者常量正确性
- 如何跨指针保持常量正确性
- 为了速度牺牲常量正确性可以吗
- file read()常量正确性
- C++NULL指针和常量正确性
- 共享指针和常量正确性