2011-05-19 93 views
6

下面是常見的錯誤的「作用域鎖」成語的例子:沒有本地變量被創建,所以鎖止裝置未生效。此代碼完美都編譯使用VC++ 2010和科莫C++在線:const正確性與臨時的實例

如果ScopedLock默認構造函數被註釋掉,那麼這兩個編譯器會給出一個錯誤:

error C2512: 'ScopedLock' : no appropriate default constructor available

(當ScopedLock正確使用,即局部變量創建:ScopedLock guard(m_mutex);,然後編譯失敗,如預期的那樣。聲明m_mutex爲可變修復問題。)

我有兩個問題:

  1. 爲什麼X::foo編譯?看起來編譯器能夠以某種方式將const Mutex&轉換爲Mutex&

  2. 什麼樣的角色扮演ScopedLock默認的構造函數,所以編譯成功?

謝謝。

更新:我找到了答案。看來,ScopedLock(m_mutex);語句創建ScopedLock類型的局部變量m_mutex。不是暫時的。這就是爲什麼ScopedLock::ScopedLock默認構造函數是必需的。

回答

4

你自己回答了這個問題。

It appears that ScopedLock(m_mutex); statement creates a local variable m_mutex of type ScopedLock

該解釋可以在標準的第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.

標準然後列出T(a);因爲這是一個真正的聲明,聲明中的一個例子。它相當於T a;

這是臭名昭着的C++「最令人頭疼的解析」的一個變種。

+0

感謝標準的答案和相關的引用。 – 2011-05-20 04:57:58

1

我敢肯定你的問題是第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)?它是否聲明瞭一個函數或什麼?而不是像提問者所期望的那樣調用構造函數? 更新:突出顯示。我認爲這只是一個變量聲明

+1

評論我在我自己的答案結尾留下的問題:我認爲你的第26行簡單地聲明瞭另一個變量,局部於X :: foo,也稱爲「m_mutex」。括號基本上被忽略。這就是它使用默認構造函數的原因。 – 2011-05-19 01:57:44

+0

@ aaron-mcdaid,是的,你是對的。剛剛發現它自己。 「ScopedLock」類型的局部變量已創建。 – 2011-05-19 02:02:16

+0

這很好。我以前從來沒有聽說過這個習語,所以謝謝你提出一個有趣的問題。 – 2011-05-19 02:04:28

0

的問題是X :: foo的()方法被聲明爲const(即括號被忽略。) - 這意味着它不會發生變異(變化)的對象。

的ScopedLock()構造不具有接受一個不可變的(常數)參照互斥對象一個過載。

定影這需要聲明m_mutex作爲可變的,或提供一個適當的過載ScopedLock()構造。我認爲前者更可取。