【问题标题】:Printing either to console or to a string/stream打印到控制台或字符串/流
【发布时间】:2026-01-31 16:45:01
【问题描述】:

我需要一个将一些文本数据(多行)转储到控制台的 C++ 函数:

void DumpData() const
{
    std::cout << "My Data 1" << std::endl;
    std::cout << "My Data 2" << std::endl;
}

这应该是默认行为,但是,也必须可以传递一些其他的流对象,而不是 std::cout,如下所示:

void DumpData(std::ostream& Stream = std::cout) const
{
    Stream << "My Data 1" << std::endl;
    Stream << "My Data 2" << std::endl;
}

现在回答我的问题:

  1. 我应该为参数使用的正确类型是什么(本例中为std::ostream&amp;)?
  2. 默认值是多少,可以直接用= std::cout吗?

另外(3.),在调用这个函数之后,如果我传递我自己的流对象,我需要逐行迭代这个流中的所有字符串。实现这一目标的最佳方法是什么?

【问题讨论】:

  • std::ostream&amp;while(std::getline(stream, line)) {...}
  • 问题 #1:嗯,您将它用作输出流,所以,是的,它似乎是正确的。问题 #2 可以通过尝试编译来回答。

标签: c++ c++11


【解决方案1】:

你为什么不自己试试呢?

这里是 in Coliru 的代码 std::coutstd::stringstream 作为示例(constness of DumpData 显然已删除):

#include <iostream>
#include <sstream>

void DumpData(std::ostream& Stream = std::cout)
{
    Stream << "My Data 1" << std::endl;
    Stream << "My Data 2" << std::endl;
}
int main() {
    DumpData();
    std::stringstream ss;
    DumpData(ss);
    std::string l;
    while(std::getline(ss, l)) {
        std::cout << l << std::endl;
    }
    return 0;
}

输出符合您的预期。

【讨论】:

    【解决方案2】:

    1 和 2 是正确的。您的另一个选择是使用std::ostringstream,但由于std::coutstd::ostream,您需要使用此签名定义另一个函数。

    要迭代自定义输出,我会convert the stream to a string,然后使用某种字符串拆分来读取每一行。

    【讨论】:

      【解决方案3】:

      添加到@Jay 的答案,只要模板参数支持&lt;&lt; 运算符,您就可以使用模板参数来使用各种流,例如std::stringstreamstd::iostream

      template <typename T> // = decltype(something)
      void DumpData(T& Stream = std::cout) const
      {
          Stream << "My Data 1" << std::endl;
          Stream << "My Data 2" << std::endl;
      }
      

      您可以更进一步,确保提供的类型 T 重载运算符 &lt;&lt;

      此外,在某些情况下,某些(可能是自定义的)流可能无法支持 std::endl,因此默认使用 \n 可能会更安全,因为它避免了不必要的刷新,因此总是更好。

      【讨论】:

      • 不要所有输出流对象(对于CharT=char 继承自std::ostream?虽然我同意模板比基于继承的接口更可取,如果您可以将定义提供给应该使用的所有地方.
      • 同样T()不等于std::cout
      • 是的,在编写声明时正在考虑其他事情。现已修复。
      最近更新 更多