Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

Consider the following:

std::ostream out(nullptr);

Is this legal and well-defined?


How about if I now do:

out << "hello world\n";

Is this legal and well-defined? If so, presumably it's a no-op of sorts?

like image 867
Lightness Races in Orbit Avatar asked Sep 05 '14 16:09

Lightness Races in Orbit


Video Answer


1 Answers

Yes, it is legal and well-defined to instantiate that stream. You can safely swap it with another stream, or give it a new pointer (this time to an extant buffer) at a later time. The output operation itself is indeed a no-op.

Here's why:

  1. The construction has no non-null precondition, and has only this postcondition:

    [C++11: 27.7.3.2/2]: Postcondition: rdbuf() == sb.

  2. Interestingly, it makes an explicit point that no operation shall be performed on sb within the constructor:

    [C++11: 27.7.3.2/4]: Remarks: Does not perform any operations on rdbuf().

  3. But note also:

    [C++11: 27.7.3.2/1]: Effects: Constructs an object of class basic_ostream, assigning initial values to the base class by calling basic_ios<charT,traits>::init(sb) (27.5.5.2).

  4. That init(sb) call has the effect of setting badbit on the stream when sb is NULL:

    [C++11: 27.5.5.2/3]: Postconditions: The postconditions of this function are indicated in Table 128.

    [C++11: Table 128]: [..] rdstate(): goodbit if sb is not a null pointer, otherwise badbit. [..]

  5. The output operation would result in actions equivalent to dereferencing a null pointer:

    [C++11: 27.7.3.1/2]: Two groups of member function signatures share common properties: the formatted output functions (or inserters) and the unformatted output functions. Both groups of output functions generate (or insert) output characters by actions equivalent to calling rdbuf()->sputc(int_type). They may use other public members of basic_ostream except that they shall not invoke any virtual members of rdbuf() except overflow(), xsputn(), and sync().

    except it never gets this far, because for basic_ostream::sentry construction:

    [C++11: 27.7.3.4/3]: If, after any preparation is completed, os.good() is true, ok_ == true otherwise, ok_ == false.

    and, for explicit operator basic_ostream::sentry::bool() const;:

    [C++11: 27.7.3.4/5]: Effects: Returns ok_.

    and:

    [C++11: 27.7.3.7/1]: Each unformatted output function begins execution by constructing an object of class sentry. If this object returns true, while converting to a value of type bool, the function endeavors to generate the requested output. [..]

    …the implication being that no output operation takes place at all when badbit is already set.

This was also the case in C++03.

like image 179
Lightness Races in Orbit Avatar answered Sep 28 '22 09:09

Lightness Races in Orbit