第6条 当心C++编译器最烦人的分析机制
当将一个存有整数(int)的文件复制到一个list中时,假设采用:
ifstream dataFile("ints.dat");
list<int> data(istream_iterator<int>(dataFile), istream_iterator<int>());
即将一对istream_iterator传入list的区间构造函数中。 这段代码可能会通过编译,但是不会实现效果
因为分析成了一个函数。。。。接着往下看
首先看三个函数声明一
1、int f(double)
2、int f(double (d)) //d两边的括号被忽略
3、int f(double) //参数名被忽略
原来可以给参数名加上圆括号.........
再看三个函数声明二:
声明了一个函数g,参数是一个指向不带任何参数的函数的指针,这个函数返回double
1、int g( double (*pf) () )
2、int g(double pf() ) //pf为隐式指针
3、int g(double()). //省去参数名
围绕参数名的括号,一(2)中,与独立括号,二(3)的区别:
围绕参数名的括号被忽略,独立的括号则表明参数列表存在:它们说明存在一个函数指针
之后再分析最开头的问题:
list<int> data(istream_iterator<int>(dataFile), istream_iterator<int>());
被分析为声明了一个函数data,返回值是list<int> ,这个data有两个参数:
第一个是dataFile, 类型是istream_iterator<int>, dataFile两边的括号是多余的,会被忽略
第二个参数没有名称,类型是指向不太参数的函数的指针,该指针返回一个 istream_iterator<int>。。。。。
好纠结。。竟然分析成这样,这是c++编译器的分析机制导致的:尽可能的解释为函数声明。
一个解决方法是:(istream_iterator<int>(dataFile)加上括号
list<int> data ( (istream_iterator<int>(dataFile)), istream_iterator<int>());
但是并不是所有编译器都接受
更好的方式是在对data的声明中避免使用匿名的istream_iterator对象,如下:
ifstream dataFile("ints.dat");
istream_iterator<int> dataBegin(dataFile);
istream_iterator<int> dataEnd;
list<int> data(dataBegin, dataEnd);
使用命名的迭代器对象与通常的STL程序风格相违背,但是为了使所有的编译器都没有二义性,并未好维护,这个代价是值得的