毫无疑问,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{}} ;