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

时间:2016-04-05 13:01:06

标签: c++ c++11 iostream libstdc++

我有以下代码让我感到惊讶(使用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)时不同。

  • 这种行为是正确/预期的吗?
  • 是否需要明确地搜索(0,std :: ios :: end)尽管打开了吗?
  • 清除状态没有任何区别。
  • 请注意字符串包含内容

2 个答案:

答案 0 :(得分:2)

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

您使用的构造函数的版本:

  

通过调用std :: basic_streambuf的默认构造函数构造一个std :: basic_stringbuf对象,用空字符串初始化字符序列,并设置模式,然后初始化关联的模式   字符序列,如同调用str(new_str)。

basic_stringbuf的默认构造函数在这里并不重要,而不是std::basic_stringbuf::str

  

删除此基础的整个基础字符序列   std :: basic_stringbuf然后配置一个新的底层字符   包含s内容副本的序列。 ...追加   streams(mode&amp; ios_base :: ate == true),pptr()== pbase()+ s.size(),   以便后续输出将附加到最后一个字符   从s

复制而来

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

  

如果包含ios_base :: in,则此缓冲区已打开以供阅读   (即if((&amp; ios_base :: in)== ios_base :: in),然后   重新定位读指针std :: basic_streambuf :: gptr:..然后newoff是指针的当前位置(在这种情况下为gptr() - eback())

总结一下:由于你没有以任何方式修改获取位置(构造函数只修改了put位置),它返回0.

答案 1 :(得分:2)

简而言之:

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

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

长期:

  • tellg()返回rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::in)
  • rdbuf()返回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返回gptr()-eback()
  • eback()返回指向get区域开头的指针
  • gptr()返回当前获取点

stringstream初始化:

  

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

     

效果:构造类basic_stringstream的对象,使用basic_iostream(&sb)初始化基类并使用basic_stringbuf(str, which)初始化sb。

     

     

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

     

效果:构造类basic_stringbuf的对象,使用basic_streambuf()初始化基类,并使用初始化模式。然后拨打str(s)

     

     

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

     

效果:将s的内容复制到basic_stringbuf基础字符序列中,并根据模式初始化输入和输出序列。

     

后置条件:

     
      
  • 如果mode & ios_base::outtrue,则pbase()指向第一个基础字符,epptr() >= pbase() + s.size()成立;

  •   
  • 如果mode & ios_base::atetrue,则pptr() == pbase() + s.size()成立,否则pptr() == pbase()true

  •   
  • 如果mode & ios_base::intrue,则eback()指向第一个基础角色,而gptr() == eback()egptr() == eback() + s.size()都会成立。

  •   

最后一位是相关的:提供ios_base::in有后置条件gptr() == eback(),而tellg()返回gptr()-eback()后,结果必须为零。