[英]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
正確使用時,即創建局部變量: ScopedLock guard(m_mutex);
然后編譯按預期失敗。將m_mutex
聲明為可變修復問題。)
我有兩個問題:
為什么X::foo
編譯? 似乎編譯器能夠以某種方式將const Mutex&
Mutex&
為Mutex&
。
扮演ScopedLock
默認構造函數的角色是什么,所以編譯成功了?
謝謝。
更新:我找到了答案。 看來是ScopedLock(m_mutex);
statement創建一個m_mutex
類型的局部變量ScopedLock
。 不是暫時的。 這就是為什么ScopedLock::ScopedLock
默認構造函數是必需的。
你自己回答了這個問題。
看來是ScopedLock(m_mutex); statement創建一個ScopedLock類型的局部變量m_mutex
解釋可在標准的6.8節歧義解決方案中找到:
在涉及表達式語句和聲明的語法中存在歧義:具有函數式顯式類型轉換[5.2.3]的表達式語句,因為其最左側的子表達式與第一個聲明符以(a)開頭的聲明無法區分。 在這些情況下,該聲明是一個聲明 。
標准然后列出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 - 這意味着它不會改變(改變)對象。
ScopedLock()構造函數沒有接受對Mutex對象的不可變(const)引用的重載。
修復此問題需要將m_mutex聲明為可變,或者提供適當的重載ScopedLock()構造函數。 我認為前者更可取。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.