为什么getline()不接受常量istream?

3

这里有一个基础问题,我正在尝试学习iostream的基础知识。

我被告知要构建一个函数来读取const istream&中的行。例如:validateFile(const istream& is)

我发现我不能使用getline()函数作为第一个参数来处理const istream&。我想知道为什么。我认为我只是在读取istream,难道函数getline()会改变它吗?

是否有可能从常量流中获取信息?


2
它从流中读取一行数据,因此会改变其状态。 - juanchopanza
3个回答

5
流的概念是按顺序从中读取一些数据,每次都会推进其内部指针。通过推进此指针,您将更改流对象。您不能从const流中读取(除非您对它们进行const转换,但这是不应该做的事情)。
编辑:实际上,我们并不关心隐藏在istream接口后面的实际流对象是否使用了一些“内部指针”。准确地说,重要的是当您读取它时,流会更改其状态,因为下一次读取它时,您会得到一个不同的结果(从流中读取下一个内容)。如果您获得了一个const对象,则意味着您不应该更改其状态。
此外,有一个原因,您不能只获取流中的数据而不更改任何内容。在文件流的情况下,原因是您想要从流中读取的下一个内容可能甚至不在内存中,流对象可能需要首先从磁盘中读取它,并更新其缓冲区等。(编辑:但这并不会改变对象的外部可见状态,因此实际上这不是一个好的论据。请阅读有关mutable关键字的更多信息。)

1
@MemyselfandI 你说得对,istream只是一个接口,实际的文件流是否使用某种指针来指向其缓冲区是一个实现细节。 - atablash

2

const流中获取数据是可能的,但您需要通过它管理的streambuf类进行读取:

#include <sstream>
#include <iostream>
#include <cstdio>

int main()
{
    const std::istringstream strm("Const stream");
    std::streambuf* buf = strm.rdbuf();

    char c;
    while ((c = buf->sbumpc()) != EOF)
        std::cout << c;
}

这应该被视为规范中的错误。对于那些愚蠢的点赞,给个-1。 - Jan Hudec
嗨,@JanHudec,我不同意。在我的看法中,拥有常量流是一个错误(BUG)。祝你有愉快的一天 :) - jrok
@jrok:显然,拥有一个常量流是没有任何意义的,但当你拥有一个常量流时,它不应该让你获取非常量指针到它的缓冲区。 - Jan Hudec

0

std::getline()(以及其他I/O函数)会设置底层流的状态以指示解析或格式化过程中的错误。这就是为什么流不能被const限定的原因。此外,在某些操作之后,流的width()会被重置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接