从空缓冲区构造“std::ostream”是否有效

Is it valid to construct an `std::ostream` from a null buffer?

本文关键字:ostream 是否 有效 std 缓冲区      更新时间:2023-10-16

请考虑以下事项:

std::ostream out(nullptr);

这是否合法且定义明确?


如果我现在这样做呢:

out << "hello worldn";

这是否合法且定义明确?如果是这样,想必是某种无操作?

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

原因如下:

  1. 构造没有非空前提条件,只有这个后置条件:

    [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)调用具有在流上设置badbit的效果,当sb为 NULL 时:

    [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的其他公共成员,但他们不得调用除overflow()xsputn()sync()以外的任何rdbuf()虚拟成员。

    除了它永远不会走到这一步,因为对于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已经设置时,根本不会发生输出操作。

03 C++也是如此。