istreambuf_iterator和ostreambuf_iterator用法简单总结

std::istreambuf_iterator 是单趟迭代器,从用来构造它的 std::basic_streambuf 对象读取相继字符。

默认构造的 std::istreambuf_iterator 迭代器被称为流尾迭代器。合法的 std::istreambuf_iterator 抵达底层流结尾时,它变得等于流尾迭代器。解引用或进一步自增它导致未定义行为。
std::ostreambuf_iterator 是单趟老式输出迭代器 (LegacyOutputIterator) ,写入相继元素到为之创建迭代器的 std::basic_streambuf 对象。实际写操作在赋值给迭代器(无论是否解引用)时进行。自增 std::ostreambuf_iterator 是无操作。

典型实现中, std::ostreambuf_iterator 仅有的数据成员是指向关联 std::basic_streambuf 的指针,和指示是否抵达文件尾条件的布尔标志。

上面这段话,摘抄自 cppreference,大概意思就是说将 stream 对象转成迭代器iterator,并把缓冲区的数据读入或读出到 iterator中。

  • 输入流缓冲区迭代器istreambuf_iterator从输入流缓冲区中读取字符。
  • 输出流缓冲区迭代器ostreambuf_iterator将字符写入到缓冲区

输入流缓冲区迭代器istreambuf_iterator功能很强大,可以从 istream、ifstream、istringstream中一次性读取所有字符内容,包括空格、tab等等空白特殊字符。istreambuf_iterator模板参数只能是charwchar_t类型,因为它的构造函数参数是basic_streambufbasic_istream类型的,而从这2个模板类派生的子类,默认就那几个。如果模板参数是wchar_t类型,那么上面提到的几个流,也应该使用wistream、wifstream、wistringstream版本的,要保持类型一致

istreambuf_iterator例子:

//从字符串流中读数据
std::istringstream iss("abcdefg");
std::string str((std::istreambuf_iterator<char>(iss)), std::istreambuf_iterator<char>());
std::cout << str << '\n';

//从文件流中读数据
std::ifstream ifs("a.txt");
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
std::cout << str << '\n';

//从文件流中读数据,并放到容器中
std::ifstream ifs("a.txt");
std::vector<char> vc((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

//是迭代器,并且也重载了 ++和* 操作符
std::ifstream ifs("a.txt");
std::vector<char> vc;
std::istreambuf_iterator beg{ifs},end;
for(;beg!=end;++beg)
{
    vc.push_back(*beg);
}

ostreambuf_iterator例子:

//写到文件
std::ofstream ofs("E:\\2.txt");
std::ostreambuf_iterator<char> ofsBeg{ ofs };
*ofsBeg++ = 'a';
*ofsBeg++ = 'b';
*ofsBeg++ = 'c';
*ofsBeg++ = 'd';
ofs.close();

在上面的例子中,看到 std::istreambuf_iterator 的写法很奇怪,要多加一个括号,具体解释请看这些博客:

https://www.zhihu.com/question/42789717/answer/94767165

https://blog.csdn.net/tax10240809163com/article/details/120856304

https://www.cnblogs.com/yangyingchao/p/3394146.html

https://qa.1r1g.com/sf/ask/881303531/

不过上面的解释,似懂非懂,解释的有些牵强。

其实,最重要的几句话就是“因为没有括号,编译器会将其视为函数声明” “这是C++的一个设计缺陷:没有给函数声明提供一个专门的关键字,于是经常会混淆函数声明与对象初始化。

所以针对这些歧义,大家给出的解决方式就是:1. 声明变量后再当做参数使用;2. 采用c++11新增的方式来初始化变量:

//提前声明变量,再传进去
std::istringstream iss("abcdefg");
std::istreambuf_iterator<char> beg(iss),end; //2个变量也可以分别声明
std::string str(beg, end);
std::cout << str << '\n';

//采用{}方式声明
std::istringstream iss("abcdefg");
std::string str{std::istreambuf_iterator<char>(iss),std::istreambuf_iterator<char>()};
std::cout << str << '\n';

//采用{}方式声明
std::istringstream iss("abcdefg");
std::string str(std::istreambuf_iterator<char>{iss}, std::istreambuf_iterator<char>{});
std::cout << str << '\n';

这边博客可以参考:https://www.cnblogs.com/cscshi/p/15701422.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值