Символ новой строки также очищает буфер?

Я понимаю, что такие вопросы, как, разница между endl а также \n много раз отвечали на ТАК. Но они только упоминают, что endl в состоянии очистить буфер на stdout, в то время как \n, не.

Итак, я понимаю, что при очистке буфера заданный ввод сохраняется в буфере и передается в stdout только когда это сталкивается endlили какой-то объяснение flush функции. Если это так, я ожидал, что следующий код:

#include <iostream>
#include <unistd.h>

int main(void)
{
std::cout << "Hello\nworld";
sleep(2);
std::cout << std::endl;

return 0;
}

Для отображения:

Через 2 секунды

Hello
World

Но фактический результат был:

Hello

Через 2 секунды

World

Почему это так ?

не должен \n также храниться в буфере и только когда endl встреченный буфер должен быть очищен / отображен на stdout, но из того, что я наблюдаю \n действует так же, как endl,

5

Решение

Преобразование комментариев в ответ.

Это зависит от того, где cout собирается Если он идет к терминалу («интерактивное устройство»), то он не может быть полностью буферизован — обычно это буферизованная строка, что означает, что символы появляются после печати новой строки, или теоретически могут быть небуферизованными. Если это происходит в канал или файл или другое неинтерактивное место назначения, endl принудительно выводит данные, даже если поток полностью буферизован, как обычно.

Я также хотел знать, не предоставил ли я ни символ новой строки, ни endl, будет ли вывод отображаться на stdout как только он достигает конца программы, я знаю, что он подходит для терминала, но применим ли он ко всем типам stdout?

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

4

Другие решения

Настройка по умолчанию для стандартных объектов потока C ++ (std::cin, std::cout, std::cerr, а также std::clogявляется то, что они синхронизируются с соответствующими потоками C (stdin, stdout, а также stderr). Синхронизация означает, что чередующийся доступ к потокам C ++ и C приводит к согласованному поведению. Например, этот код должен генерировать строку hello, world:

std::cout << "hel";
fprintf(stdout, "lo,");
std::cout << " wo";
fprintf(stdout, "rld");

Стандарт C ++ не устанавливает, как реализована эта синхронизация. Один из способов реализовать это — отключить любую буферизацию для std::cout (и семья) и сразу же получить доступ stdout, То есть приведенный выше пример может сразу записать отдельные символы в stdout,

Если символы на самом деле написаны stdout настройка по умолчанию для режима буферизации для stdout будет использоваться. Я не могу найти спецификацию в стандарте, но обычно по умолчанию для режима буферизации stdout является _IOLBF когда он подключен к интерактивному потоку (например, к консоли), то есть буфер сбрасывается в конце строк. По умолчанию для записи в файл обычно _IOFBFвыходной сигнал сбрасывается при записи полного буфера. В результате написания новой строки std::cout может привести к очистке буфера.

Потоки в C ++ обычно настроены для буферизации. То есть запись новой строки в файл, как правило, не приводит к немедленному появлению выходных данных (он будет появляться немедленно, только если символ вызовет переполнение буфера потока, установленного как небуферизованный). Поскольку синхронизация с stdout часто не требуется, например, когда программа всегда использует std::cout для записи в стандартный вывод, но вызывает резкое замедление вывода на стандартный вывод (отключение буферизации для потока делает их медленный) синхронизацию можно отключить:

std::ios_base::sync_with_stdio(false);

Это отключает синхронизацию для всех потоковых объектов. Для плохой реализации не может быть никакого эффекта, в то время как хорошая реализация включит буферизацию для std::cout что приводит к значительному ускорению и, возможно, также отключает буферизацию строки.

Как только поток C ++ буферизуется, нет встроенного способа вызвать его сброс при написании новой строки. Основная причина этого заключается в том, что работа с буферизацией строки потребует проверки каждого символа потоковым буфером, который эффективно запрещает массовые операции над символами и тем самым вызывает существенное замедление. При необходимости буферизация строки может быть реализована через простой поток фильтрации буфера. Например:

class linebuf: public std::streambuf {
std::streambuf* sbuf;
public:
linebuf(std::streambuf* sbuf): sbuf(sbuf) {}
int_type overflow(int_type c) {
int rc = this->sbuf->sputc(c);
this->sbuf->pubsync();
return rc;
}
int sync() { return this->sbuf->pubsync(); }
};
// ...
int main() {
std::ios_base::sync_with_stdio(false);
linebuf sbuf(std::cout.rdbuf());
std::streambuf* origcout = std::cout.rdbuf(&sbuf);

std::cout << "line\nbuffered\n";

std::cout.rdbuf(origcout); // needed for clean-up;
}

tl; dr: стандарт C ++ не имеет концепции буферизации строк, но он может получить ее, когда стандартный ввод-вывод синхронизируется из поведения C stdout,

3

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector