当 std::stringstream 由 ("some content", std::ios::in|std::ios::ate) 构造时,tellg() 的预期行为是什么?

What is the expected behavior of tellg() when std::stringstream is constructed with ("some content", std::ios::in|std::ios::ate)?

我有以下一段代码让我感到惊讶(使用 libstdc++4.8)...

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main() {
    std::string s("some content");
    std::stringstream ss(s, std::ios::in|std::ios::ate);
    std::istream& file = ss;
    //ss.clear(); Makes no difference...
    std::cout << "tellg() pos: " << file.tellg() << std::endl;
    return 0;
}

... 具有以下输出。

tellg() pos: 0

此行为与使用 std::ifstream(std::ios::ate) 时不同。

这完全符合标准告诉我们的内容。以下是相关详情:

您使用的构造器版本:

Constructs a std::basic_stringbuf object by calling the default constructor of std::basic_streambuf, initializes the character sequence with an empty string, and sets the mode to which, than followed by initializing the associated character sequence as if by calling str(new_str).

basic_stringbuf 的默认构造函数在这里并不有趣,比 std::basic_stringbuf::str:

Deletes the entire underlying character sequence of this std::basic_stringbuf and then configures a new underlying character sequence containing a copy of the contents of s. ... For append streams (mode & ios_base::ate == true), pptr() == pbase() + s.size(), so that subsequent output will be appended to the last character copied from s

最后,tellg(),它在缓冲区上调用 pubseekoff

If which includes ios_base::in and this buffer is open for reading (that is, if ((which & ios_base::in) == ios_base::in), then repositions the read pointer std::basic_streambuf::gptr: .. then newoff is the current position of the pointer (gptr()-eback() in this case)

总结一下:因为你没有以任何方式修改 get 位置(构造函数只修改 put 位置),它 returns 0.

简而言之:

tellg() returns gptr()-eback() 并在 stringstream(因此 basic_stringbuf)构造函数中提供 ios_base::in 标志具有后置条件gptr() == eback().

因此,0 是预期/强制执行的。

长:

  • tellg() returns rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::in)
  • rdbuf() returns const_cast<basic_stringbuf*>(&sb).
  • pubseekoff(0, std::ios_base::cur, std::ios_base::in) 呼叫 seekoff(0, std::ios_base::cur, std::ios_base::in)
  • seekoff returns gptr()-eback()
  • eback()returns指向获取区开始的指针
  • gptr()returns当前获得点数

stringstream初始化:

basic_stringstream (basic_string const &str, ios_base::openmode which);

Effects: Constructs an object of class basic_stringstream, initializing the base class with basic_iostream(&sb) and initializing sb with basic_stringbuf(str, which).

 

basic_stringbuf(basic_string const &str, ios_base::openmode which)

Effects: Constructs an object of class basic_stringbuf, initializing the base class with basic_streambuf(), and initializing mode with which. Then calls str(s).

 

void basic_stringbuf::str(const basic_string<charT,traits,Allocator>& s);

Effects: Copies the content of s into the basic_stringbuf underlying character sequence and initializes the input and output sequences according to mode.

Postconditions:

  • If mode & ios_base::out is true, pbase() points to the first underlying character and epptr() >= pbase() + s.size() holds;

  • if mode & ios_base::ate is true, pptr() == pbase() + s.size() holds, otherwise pptr() == pbase() is true.

  • If mode & ios_base::in is true, eback() points to the first underlying character, and both gptr() == eback() and egptr() == eback() + s.size() hold.

最后一位相关:提供 ios_base::in 具有后置条件 gptr() == eback() 并且由于 tellg() returns gptr()-eback() 结果需要为零.