stl容器使用中的经验(八)对于逐个字符的输入请考虑使用 istreambuf_iterator

先来看个例子:

ifstream inputFile("ints.dat");
list<int> data(istream_iterator<int>(inputFile), istream_iterator<int>());

上面的这两行代码,貌似是将两个 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<int> data(istream_iterator<int>(inputFile), istream_iterator<int>());

那么我们就能够很明显的看出,第二行代码是申明了一个名称为data的函数。函数返回值类型为 list<int>,函数有两个参数。

  1. 第一个参数名称为 inputFile,类型为istream_iterator<int>
  2. 第二个参数没有名称。类型是指向不带参数的函数的指针,该函数的返回值是istream_iterator<int>

所以,上面的代码不会达到我们逾期的效果。

就跟下面的例子一样,是我们经常犯的错误,下面第二行代码并没有定义一个Widget的对象,而是申明了一个,没有参数,返回值类型为Widget,名称为w的函数。

class Widget{...};

Widget w();

按照下面的方式解决上述的问题。让代码不要出现二义性。

ifstream inputFile("ints.dat");
istream_iterator<int> begin(inputFile);
istream_iterator<int> end;
list<int> data(begin, end);

我们再来看下下面的例子:

#include<iostream>
#include <fstream>
#include <ctime>
#include <iterator>
#include <cassert>

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<char>(inputData)),  istream_iterator<char>());
	time_t t2 = time(NULL);

	cout << t1 << " " << t2 << endl; //1634635857 1634635866
	
	time_t t3 = time(NULL);
	string data2((istreambuf_iterator<char>(inputData)),  istreambuf_iterator<char>());
	time_t t4 = time(NULL);
	
	cout << t3 << " " << t4 << endl;   //1634635923 1634635923

	return 0;
}

上面的例子有两种从文件读取字符并构建了一个string的对象,前一种使用了 istream_iterator后一种使用的是istreambuf_iterator,两者的区别也是显而易见的。

  1. istream_iteratoristreambuf_iterator耗时更久
  2. istream_iterator默认是忽略字符中的空格的
  3. 需要设置 inputData.unsetf(ios::skipws);

因此,如果需要从输入流中逐个读取字符,istreambuf_iterator是个不错的选择,就不必要进行格式化输入,因为 istream_iterator在调用其 operator << 时其实是进行了格式化的输入。但istreambuf_iterator从一个输入流中 stream s 读取下一个字符是通过 s.rdbuf()->sgetc()完成的。 如果追求输入的效率,那么选择istreambuf_iterator

同样的,输出的时候也可以选择 ostreambuf_iterator

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值