栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

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

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

先来看个例子:

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,函数有两个参数。

  1. 第一个参数名称为 inputFile,类型为istream_iterator
  2. 第二个参数没有名称。类型是指向不带参数的函数的指针,该函数的返回值是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,两者的区别也是显而易见的。

  1. istream_iterator较istreambuf_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。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/334895.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号