想要 ostringstream 修改传递的字符串

Want ostringstream to modify passed string

我想std::ostringstream修改我传递给它的字符串:

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

void My_Function(std::string& error_message)
{
  std::ostringstream error_stream(error_message);
  // For Nipun Talukdar:
  /* Perform some operations */
  if (/* operation failed */)
  {
      error_stream << "Failure at line: "
                   << __LINE__
                   << ", in source file: "
                   << __FILE__
                   << "\n";
  }
  return;
}

int main(void)
{
  std::string error_message;
  My_Function(error_message);
  std::cout << "Error is: \""
            << error_message
            << "\"\n";
  return 0;
}

使用上面的代码,error_message的输出是空的。

这是因为,according to cppreference.com,接受 std::streamstd::basic_ostream 的构造函数接受了 const 的引用一个std::string。这意味着 std::basic_ostringstream 不会修改传递给它的字符串。引用的参考文献甚至说 std::ostringstream 复制了传递给它的字符串

为了解决这个问题,我更改了函数:

void My_Second_Function(std::string& error_message)
{
  std::ostringstream error_stream;
  error_stream << "Failure at line: "
               << __LINE__
               << "\n";
  error_message = error_stream.str();  // This is not efficient, making a copy!
  return;
}

是否有更有效的方法来对字符串执行格式化输出,例如直接写入(即无需从流中复制)?

我正在使用 Visual Studio 2010,不支持 C++11。出于开店考虑,升级到2013的理由没有通过。所以我不能使用 C++11 或 C++14 功能。

使用流缓冲区并将 put 指针设置为字符串的内部数据:

struct nocopy : std::streambuf
{
    nocopy(std::string& str)
    { this->setp(&str[0], &str[0] + str.size()); }
};

struct nocopy_stream : virtual private nocopy, std::ostream
{
    nocopy_stream(std::string& str)
        : nocopy(str)
        , std::ostream(this)
    { }
};

void My_Function(std::string& error_message)
{
  nocopy_stream error_stream(error_message);
  error_stream << "Failure at line: "
               << __LINE__
               << "\n";
}

int main(void)
{
  std::string error_message;
  error_message.resize(1000);

  My_Function(error_message);
  std::cout << "Error is: \""
            << error_message
            << "\"\n";
}

对于此示例,error_message 必须设置为足够大的大小,因为我们不会覆盖 overflow() 并且基础 class 版本什么都不做。但是,您可以覆盖它以进行正确的大小调整。