Подтвердить что ты не робот

Можно ли построить "std:: ostream" из нулевого буфера?

Рассмотрим следующее:

std::ostream out(nullptr);

Является ли это законным и четко определенным?


А если я сейчас сделаю:

out << "hello world\n";

Является ли это законным и четко определенным? Если да, то, по-видимому, это не-op рода?

4b9b3361

Ответ 1

Да, это законно и четко определено для создания экземпляра этого потока. Вы можете безопасно обменять его другим потоком или дать ему новый указатель (на этот раз для существующего буфера) в более позднее время. Сама операция вывода действительно не работает.

Вот почему:

  • Конструкция не имеет ненулевого предварительного условия и имеет только это постусловие:

    [C++11: 27.7.3.2/2]: Постусловие: rdbuf() == sb.

  • Интересно, что он явно указывает, что в sb внутри конструктора не должно выполняться никаких операций:

    [C++11: 27.7.3.2/4]: Примечания: Не выполняет никаких операций с rdbuf().

  • Но обратите внимание также:

    [C++11: 27.7.3.2/1]: Эффекты: Создает объект класса basic_ostream, назначая начальные значения базовому классу, вызывая basic_ios<charT,traits>::init(sb) (27.5.5.2).

  • Этот вызов init(sb) влияет на установку badbit в потоке, когда sb имеет значение NULL:

    [C++11: 27.5.5.2/3]: Постусловия: постусловия этой функции указаны в таблице 128.

    [C++11: Table 128]: [..] rdstate(): goodbit если sb не является нулевым указателем, в противном случае badbit. [..]

  • Операция вывода приведет к действиям, эквивалентным разыменованию нулевого указателя:

    [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() true, ok_ == 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, функция пытается сгенерировать запрошенный выход. [..]

    & hellip; подразумевается, что никакой выходной операции вообще не происходит, когда badbit уже установлен.

Это было также в С++ 03.