「C++」C++中最令人頭痛的語法解析是什麼?

毫無疑問,C++是一個很複雜的語言,C++中有一個很經典的術語叫:

最令人頭痛的語法解析


定義

最令人頭痛的語法解析是C++編程語言中句法歧義消解的一種特殊形式。大神Scott Meyers在有效的STL(2001)中使用了這個術語。(1)它在C++語言標準的第8.2節中被正式定義。

看下面的代碼:

<code>class Timer { public: Timer(); }; class TimeKeeper { public: TimeKeeper(const Timer& t); int get_time(); }; int main() { TimeKeeper time_keeper(Timer()); return time_keeper.get_time(); }/<code>

隨後我們在寫出下面的代碼:

<code> TimeKeeper time_keeper(Timer());/<code>

這段代碼似乎有歧義,因為它可以被解釋為

定義並初始化一個叫time_keeper的類。函數申明,聲明一個叫time_keeper的函數,返回值類型為TimeKeeper.

大多數程序員期望第一個,但是C++標準要求它被解釋為第二個。

例如,g++給出以下錯誤消息:

<code>time_keeper.cc: In function ‘int main()’: time_keeper.cc:15: error: request for member ‘get_time’ in ‘time_keeper’, which is of non-class type ‘TimeKeeper(Timer (*)())’/<code>

上面錯誤的意思是,我們不應該這麼調用get_time函數,因為編譯器把它當成了一個函數聲明,沒有成員變量,我們在main函數中這麼調用就會報錯。


clang中會發出這樣的警告:

<code>clang++ time_keeper.cc timekeeper.cc:14:25: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] TimeKeeper time_keeper(Timer()); ^~~~~~~~~ timekeeper.cc:14:26: note: add a pair of parentheses to declare a variable TimeKeeper time_keeper(Timer()); ^ ( ) timekeeper.cc:15:21: error: member reference base type 'TimeKeeper (Timer (*)())' is not a structure or union return time_keeper.get_time();/<code>


解決辦法

多用一個括號
TimeKeeper time_keeper((Timer()));使用拷貝初始化
TimeKeeper time_keeper = TimeKeeper(Timer());C++11以後,可以使用uniform initialization
TimeKeeper time_keeper{Timer()};
TimeKeeper time_keeper(Timer{});
TimeKeeper time_keeper{Timer{}};