毫無疑問,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());
TimeKeeper time_keeper{Timer()};
TimeKeeper time_keeper(Timer{});
TimeKeeper time_keeper{Timer{}} ;