2014-01-15 3 views
1

Моя программа печатает большое количество коротких строк до cout.Сообщите `endl`, чтобы не смыть

Как немного надуманный пример, мои линии выглядят немного как это:

cout<<"The variable's value is: "<<variable<<endl; 

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

Теперь, некоторые люди в интернете говорят, что я мог бы сделать это вместо:

cout<<"The variable's value is: "<<variable<<"\n"; 

Но это не кажется хорошим решением, потому что endl абстрагируется от конкретной системы конкретных путей конец линии может быть указано, где \n нет. Это также кажется плохим решением, потому что, если мне нужно буферизировать в будущем, мне пришлось бы изменить всю базу кода.

Поэтому, я спрашиваю, есть ли способ отключить буферный аспект endl?

EDIT

Далее рытье кажется, чтобы указать, что оба endl и \n соблюдать различные способы ОС может выбрать, чтобы закончить это строки. It also seems, что выходной поток обнаруживает, находится ли он в потенциально интерактивной ситуации, а буферы и флаги соответственно. Поэтому: проблема может быть решена путем ручного указания выходного потока для выполнения агрессивной буферизации ... если я смогу понять, как это сделать.

+0

возможно дубликат [C++ - епсИ и очистки буфера] (http://stackoverflow.com/questions/4751972/c-endl-and-flushing-the-buffer) –

+0

Важно отметить, что это OS/терминал. В спецификации нет ничего, что требовало бы флеша на новой линии. –

+6

@ ling.s: Я не вижу, как этот вопрос является дубликатом того, с которым вы связались. –

ответ

8

епсИ абстрагирует конкретные пути для конкретной установки может быть специфицированы конец линии, где, как \ п не».

std::endl определяется выходом '\n' с последующим флеша. Правильная абстракцию системная новинка - только '\n'.

Во избежание флешей, один просто не использует std::endl. Кроме того, стандартный вывод может быть буферизирован в линию, если он подключен или может быть подключен к интерактивному устройству, в в этом случае новая строка ch aracter очистит поток. Если это проблема, используйте ofstream, подключенный к именованному файлу. Я думаю, что в Unix-подобных системах буферизация строк происходит только тогда, когда стандартный вывод является терминалом.

+4

На самом деле это не вопрос. он хочет предотвратить приливы. Многие платформы также будут скрыты, если они видят новую строку. –

+0

Мне кажется, это точно отвечает на вопрос. Вы избегаете флеша, просто записывая «\ n», и вы не теряете мобильности. –

+2

@AlanStokes: Нет гарантии, что новая строка не вызовет флеш. Я все же скучал по тому, что он получал на первый взгляд. Я не могу найти пуленепробиваемый способ сделать это. Может быть, напишите на 'cerr'? Hackish, но ... –

4

endl промывки. Если вы не хотите этого поведения, не используйте endl. Если вы хотите изменить свой код легко использовать свой собственный манипулятор:

inline std::ostream& myendl(std::ostream& os){ 
    os.put(os.widen('\n')); 
    return os; 
} 

Таким образом, вы можете легко изменить поведение вашего myendl на одном месте.

+1

'os.widen()' не требуется, поскольку тип символа известен. – 0x499602D2

3

Согласно http://en.cppreference.com/w/cpp/io/manip/endl

:: Вставки End L, с лицевой линии символ в выходной последовательности зева и выравнивались его как при вызове os.put(os.widen('\n')) с последующим os.flush().

Таким образом, вы хотите просто написать os.put(os.widen('\n')), который должен быть из этого определения безопасным и портативным и правильным, а также для удовлетворения ваших основных потребностей.

1

Существует std :: nounitbuf, который документирован, чтобы иметь некоторый эффект в этом вопросе. Однако я не заметил никакой разницы. Для того, чтобы обойти все идеи ostream в том, когда или если не смывать я попытался это:

std::ostringstream oss; 
// std::cout << std::nounitbuf; 
for(int i = 0; i < 1000000; i++){ 
// std::cout << "Test " << "file" << '\n'; 
    oss << "Test " << "file" << '\n'; 
} 
std::cout << oss.str(); 

Это улучшенное время выполнения от ~ 33 сек до ~ 25csec.

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

./program | grep -v "The variable" 
1

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

#include <iostream> 

static int disable() { 
    static int index(std::ios_base::xalloc()); 
    return index; 
} 

class save_buffer 
{ 
public: 
    save_buffer(std::ios& other) 
     : str(other), buf(other.rdbuf()) 
    { } 

    ~save_buffer() { str.rdbuf(buf); } 
private: 
    std::ios& str; 
    std::streambuf* buf; 
}; 

class syncing_buffer_optional : public std::streambuf, private save_buffer 
{ 
public: 
    syncing_buffer_optional(std::ostream& other) 
     : save_buffer(other), 
      buf(other.rdbuf()), 
      disable_sync(other.iword(disable())) 
    { } 

    std::streambuf::int_type overflow(std::streambuf::int_type c) 
    { 
     buf->sputc(c); 
     return 0; 
    } 

    int sync() 
    { 
     return disable_sync? 0: buf->pubsync(); 
    } 
private: 
    std::streambuf* buf; 
    bool disable_sync; 
}; 

std::ostream& flush_on_endl(std::ostream& os) 
{ 
    os.iword(disable()) = false; 
    return os; 
} 

std::ostream& noflush_on_endl(std::ostream& os) 
{ 
    os.iword(disable()) = true; 
    return os; 
} 


std::ostream& endl(std::ostream& os) 
{ 
    syncing_buffer_optional eb(os); 
    os.rdbuf(&eb); 

    return os << std::endl; 
} 

int main() 
{ 
    std::cout << noflush_on_endl << endl; 
} 
+0

Примечание: Мне нужно создать функцию 'endl' из-за зависимостей между временем жизни между буфером и потоком. Более того, даже если буфер был статичным, как мы можем различать вызов 'std :: endl' и произвольный' flush() '? – 0x499602D2

Смежные вопросы