【问题标题】:Is there a way to use an "ostream" to write over an existing instance of std::string有没有办法使用“ostream”来覆盖现有的 std::string 实例
【发布时间】:2010-10-19 07:19:16
【问题描述】:

我知道各种 ostream 都有自己的内部缓冲区。 我必须知道是否有某种 ostream 接受实例 std::string 并在该实例上写入。

(我想避免冗余副本)

注意:我的问题是关于标准库的,不要向我提供其他可以做到这一点的库,我知道它们存在。 :)

编辑:请求更具体...这是我想要的,请考虑以下代码:

std::string str = "bla bla bla ";
std::ospecialstream o(str);
o << 34 << " bla bla";
std::cout << str; //console output : "bla bla bla 34 bla bla"

我想要 ospecialstream 这样它就不会将 str 内容复制到某个内部缓冲区,而是写入 str 的同一个实例。

编辑#2 我出于性能原因需要它,ostringstream 将在使用字符串创建时创建一个 memcopy,并且在检索内容时也会创建一个 memcpy。

【问题讨论】:

  • 我严重怀疑这是否能解决您可能遇到的任何性能问题。这是过早的优化。

标签: c++


【解决方案1】:

std::ostringstream 部分 sstream 标头。

这个怎么样:

void appendStuff(string& in) {
   ostringstream os;
   os << 34 << " bla bla";
   in += os.str();
}

【讨论】:

  • ostringstream 拥有自己的 stringbuf。
  • @Pontus Gagge:是的,当然可以。 IMO 这就是 OP 想要的。
  • 这没有帮助有两个原因。我想要一个基于预定义字符串的 ostream。另一个问题是,当我想从 ostringstream 检索字符串时,它会给我另一个副本。
  • @dirkgently:好吧,这不是 OP 所要求的,但我同意这是所需要的(而不是在现有的 std::string 中四处乱窜)。
  • @yossi1981:由于这是一个非常具体的要求(没有副本),您可能不得不自己动手。我仍然会选择 ostringstream(副本是唯一的绑定因素吗?)
【解决方案2】:

如果您问是否可以更改 ostream 的缓冲,那么答案是肯定的。但是,根据您实际希望缓冲区执行的操作,这并不是一项特别简单的任务。您将需要查阅像 Langer & Kreft 这样的书以获取更多信息。

L&K 有一个如何实现无缓冲输出流的示例 - 它从本书的第 229 页开始。这里复现太长了,但基本上需要重新定义派生的streambuf类的overflow()方法。

请注意,这本书无法在线获得,但源代码显然是 - 请参阅此page 了解详细信息。

【讨论】:

  • 我会参考那本书,我想我可以认为你的帖子是一个很好的答案,+1,谢谢
【解决方案3】:

简短回答:没有

长答案:是的,但这需要编写自己的 streambuf 类,然后使用 rdbuf 设置它。此外,现在已弃用的 strstream 几乎可以满足您的需求,并且可能仍然存在于您的编译器库中。

【讨论】:

    【解决方案4】:
    #include <iostream>
    #include <string>
    
    class intostring : public std::basic_streambuf<char> {
      std::string &str;
    public:
      intostring(std::string &pstr):str(pstr) {}
      virtual std::streamsize xsputn(const char *const p, const std::streamsize n) {
        str.append(p, n);  
      }
    };
    
    int main() {
      std::string s("Original string: ");
    
      intostring newbuf(s);
    
      std::streambuf *oldbuf = std::cout.rdbuf(&newbuf);
      std::cout << "Should go to string" << std::endl;
      std::cout.rdbuf(oldbuf);  
    
      std::cout << "Should go to console again ... and here's the string: '" 
                << s << "'" << std::endl;
    }
    

    输出:

    应该再次进入控制台......这是字符串:'原始字符串:应该转到字符串'

    【讨论】:

      猜你喜欢
      • 2013-06-24
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2016-09-10
      • 2020-05-11
      • 2018-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多