从空缓冲区构造`std :: ostream`是否有效?

时间:2014-09-05 16:57:08

标签: c++ c++11 std iostream

请考虑以下事项:

std::ostream out(nullptr);

这是否合法且定义明确?


如果我现在这样做:

out << "hello world\n";

这是合法且明确的吗?如果是这样的话,大概是一种无操作的行为?

1 个答案:

答案 0 :(得分:24)

是的,实例化该流是合法且定义良好的。您可以安全地将其与另一个流交换,或者稍后给它一个新的指针(这次是对现有的缓冲区)。输出操作本身确实是无操作。

这就是原因:

  1. 构造没有非null前置条件,并且只有这个后置条件:

      

    [C++11: 27.7.3.2/2]:后置条件:rdbuf() == sb

  2. 有趣的是,它明确指出在构造函数中sb不应该执行任何操作:

      

    [C++11: 27.7.3.2/4]:备注:不对rdbuf()执行任何操作。

  3. 但请注意:

      

    [C++11: 27.7.3.2/1]:效果:构造类basic_ostream的对象,通过调用basic_ios<charT,traits>::init(sb)(27.5.5.2)将初始值分配给基类。

  4. init(sb)为NULL时,badbit调用会对流设置sb

      

    [C++11: 27.5.5.2/3]:后置条件:此函数的后置条件如表128所示。

         

    [C++11: Table 128]: [..] rdstate()goodbit如果sb不是空指针,否则   badbit [..]

  5. 输出操作导致相当于取消引用空指针的操作:

      

    [C++11: 27.7.3.1/2]:两组成员函数签名共享公共属性:格式化的输出函数(或插入器)和未格式化的输出函数。 两组输出函数都通过等同于调用rdbuf()->sputc(int_type)的操作生成(或插入)输出字符。他们可能使用basic_ostream的其他公共成员,除非他们不会调用任何虚拟成员除rdbuf()overflow()xsputn()之外的sync()成员。

    除了它永远不会这么远,因为basic_ostream::sentry构造:

      

    [C++11: 27.7.3.4/3]:如果在完成任何准备工作后,os.good()trueok_ == true则为ok_ == false

    explicit operator basic_ostream::sentry::bool() const;

      

    [C++11: 27.7.3.4/5]:效果:返回ok_

      

    [C++11: 27.7.3.7/1]:每个未格式化的输出函数通过构造类sentry的对象开始执行。如果此对象返回true,则在转换为类型bool的值时,该函数会尝试生成请求的输出。 [..]

    ......这意味着当badbit已经设置时,根本不会发生任何输出操作。

  6. This was also the case in C++03.