最近在看STL,其中讲到容器这一部分的时候,有以下两个式子,有点疑惑:
deque<int> c(istream_iterator<int>(cin), istream_iterator<int>()); () //函数声明
deque<int> c((istream_iterator<int>(cin)), (istream_iterator<int>())); () //定义一个容器
式子原本的含义都是要定义一个容器,容器的内容从标准输入获取。
这里主要分析下两个式子产生这种区别的原因:
1、式子(1),我们知道,c++中定义一个变量可以是:
<pre name="code" class="cpp">int a; //标准的定义,在声明式中也可以作为参数类型声明
int(a); //另一种定义,实际就是利用了括号的分割作用,与上一种本质相同
int(); //定义一个匿名的变量,在声明式中是作为一个函数声明,形同int (*)()
int(); //定义一个匿名变量,并用1初始化</pre>
注意上面几种形式,尤其是第三种形式是理解上述两个式子区别的关键。
好了,这样子的话,表达式中,
- istream_iterator<int>(cin)既可以理解为定义一个用cin去初始化的匿名istream_iterator<int>变量,也可以理解为定义一个知名变量,即istream_iterator<int> cin;
- istream_iterator<int>()可以理解为定义一个默认初始化的匿名变量,也可以理解为声明一个函数指针,即istream_iterator<int> (*)();
既然这样的话,对于(1)式,就用两种理解方式:
- 一是可以理解为c是一个函数声明,其参数是一个istream_iterator<int>变量,一个函数指针istream_iterator<int> (*)(),返回值是deque<int>;
- 二是可以理解为定义一个deque<int>的变量c,用两个iterator迭代器来对变量c进行初始化,因为deque有一种初始化方式就是deque<T> c(begin, end);
在这种情况下,编译器默认优先将(1)式理解为函数声明。
2、那么,为什么在(2)式中将参数加上括号后就可以避免这种歧义呢?
在c++中,函数的声明形式必须是 returnType fun(type1, type2, ...),对于returnType fun((type1),( type2), ...)的形式,是不能作为函数声明来通过编译的,由此,在(2)式中将参数都加上括号后,即可自动消除表达式是函数声明的可能,所以语义也就很清晰了,即定义一个容器。
由此得到的结论是:
编译器总是优先看作声明,其次看作表达式。