先来看个例子:
ifstream inputFile("ints.dat");
list data(istream_iterator(inputFile), istream_iterator());
上面的这两行代码,貌似是将两个 isteam_iterator 迭代器传给list容器的构造函数,从而将文件中的数据拷贝到容器中。
但是,结果真的如我们所料吗?首先我们看下下面的代码。
int f(double d); int f(double (d)); int f(double);
这三行代码效果是相同的,都是定义了一个函数,函数的返回值的int类型,参数是double类型。
下面的这行代码也是定义了一个函数,函数 g 以指向函数的指针为参数
int g( dlouble (*pf)() );
(*pf)() 是一个指向一个不带任何参数的函数的指针,返回值为double类型,返回值做了 函数 g 的参数。
那么下面的这个函数申明和上面表达了同样的含义。
int g( dlouble pf() );
如果我们将参数名称省略。
int g( dlouble () );
那么这个函数和上面的 int f(double (d));有什么区别呢?
我们可以看到,函数 f 的括号是在实参的两边,括号存在和不存在效果是一样的,但是函数 g 则不同,存在一个空的括号,根据推导,这个空的括号是有具体意义的,是存在一个函数指针参数的。
接下来,我们看下最开始的问题。
ifstream inputFile("ints.dat");
list data(istream_iterator(inputFile), istream_iterator());
那么我们就能够很明显的看出,第二行代码是申明了一个名称为data的函数。函数返回值类型为 list
- 第一个参数名称为 inputFile,类型为istream_iterator
- 第二个参数没有名称。类型是指向不带参数的函数的指针,该函数的返回值是istream_iterator
所以,上面的代码不会达到我们逾期的效果。
就跟下面的例子一样,是我们经常犯的错误,下面第二行代码并没有定义一个Widget的对象,而是申明了一个,没有参数,返回值类型为Widget,名称为w的函数。
class Widget{...};
Widget w();
按照下面的方式解决上述的问题。让代码不要出现二义性。
ifstream inputFile("ints.dat");
istream_iterator begin(inputFile);
istream_iterator end;
list data(begin, end);
我们再来看下下面的例子:
#include#include #include #include #include using namespace std; int main() { ifstream inputData("intdata.dat"); assert(inputData.is_open()); inputData.unsetf(ios::skipws); time_t t1 = time(NULL); string data((istream_iterator (inputData)), istream_iterator ()); time_t t2 = time(NULL); cout << t1 << " " << t2 << endl; //1634635857 1634635866 time_t t3 = time(NULL); string data2((istreambuf_iterator (inputData)), istreambuf_iterator ()); time_t t4 = time(NULL); cout << t3 << " " << t4 << endl; //1634635923 1634635923 return 0; }
上面的例子有两种从文件读取字符并构建了一个string的对象,前一种使用了 istream_iterator后一种使用的是istreambuf_iterator,两者的区别也是显而易见的。
- istream_iterator较istreambuf_iterator耗时更久
- istream_iterator默认是忽略字符中的空格的
- 需要设置 inputData.unsetf(ios::skipws);
因此,如果需要从输入流中逐个读取字符,istreambuf_iterator是个不错的选择,就不必要进行格式化输入,因为 istream_iterator在调用其 operator << 时其实是进行了格式化的输入。但istreambuf_iterator从一个输入流中 stream s 读取下一个字符是通过 s.rdbuf()->sgetc()完成的。 如果追求输入的效率,那么选择istreambuf_iterator。
同样的,输出的时候也可以选择 ostreambuf_iterator。



