Какое значение имеет включение
ios_base::sync_with_stdio(false);
cin.tie(NULL);
в программах на C ++?
В моих тестах это ускоряет время выполнения, но есть ли тестовый пример, о котором я должен беспокоиться, включив его?
Всегда ли 2 утверждения должны быть вместе, или первого достаточно, т. Е. Игнорировать cin.tie(NULL)
?
Кроме того, допустимо ли использовать одновременно команды C и C ++, если для него установлено значение false
?
https://www.codechef.com/viewsolution/7316085
Приведенный выше код работал нормально, пока я не использовал scanf/printf
в программе на C ++ значение как true
. В этом случае он дал ошибку сегментации. Что может быть этому объяснению?
Ответы:
Эти два вызова имеют разные значения, которые не имеют ничего общего с производительностью; тот факт, что он ускоряет время выполнения, является (или может быть ) лишь побочным эффектом. Вы должны понимать, что делает каждый из них, и не включать их вслепую в каждую программу, потому что они выглядят как оптимизация.
ios_base::sync_with_stdio(false);
Это отключает синхронизацию между стандартными потоками C и C ++. По умолчанию все стандартные потоки синхронизируются, что на практике позволяет смешивать ввод-вывод в стилях C и C ++ и получать разумные и ожидаемые результаты. Если вы отключите синхронизацию, потокам C ++ разрешено иметь свои собственные независимые буферы, что делает смешивание ввода-вывода в стилях C и C ++ приключением.
Также имейте в виду, что синхронизированные потоки C ++ являются потокобезопасными (вывод из разных потоков может чередоваться, но вы не получаете гонок за данные).
cin.tie(NULL);
Это развязывает
cin
отcout
. Связанные потоки гарантируют, что один поток автоматически очищается перед каждой операцией ввода-вывода в другом потоке.По умолчанию
cin
привязан дляcout
обеспечения разумного взаимодействия с пользователем. Например:std::cout << "Enter name:"; std::cin >> name;
Если
cin
иcout
связаны, вы можете ожидать, что вывод будет сброшен (т.е. станет видимым на консоли) до того, как программа запросит ввод от пользователя. Если вы развяжете потоки, программа может заблокировать ожидание, пока пользователь введет свое имя, но сообщение «Введите имя» еще не отображается (посколькуcout
по умолчанию оно буферизуется, вывод сбрасывается / отображается на консоли только по запросу или когда буфер заполнен).Так что, если вы отвязываетесь
cin
отcout
, вы должны обязательно промыватьcout
вручную каждый раз, когда хотите что-то отобразить, прежде чем ожидать вводаcin
.В заключение, узнайте, что делает каждый из них, поймите последствия, а затем решите, действительно ли вы хотите или нуждаетесь в возможном побочном эффекте повышения скорости.
источник
cout
Буферизуется по какой-то причине, если вы слишком часто очищаете его, когда он вам на самом деле не нужен, вы можете увидеть снижение производительности.scanf()
, либо полностью отключить буферизацию, либо переключиться на буферизацию строки (которая должна сбрасываться после новой строки или при чтении вводаstdin
- см. Linux.die.net/man/3/setlinebuf ).Это сделано для синхронизации операций ввода-вывода из мира C и C ++. Если вы синхронизируете, то у вас есть гарантия, что заказы всех операций ввода-вывода соответствуют вашим ожиданиям. В общем, проблема заключается в буферизации операций ввода-вывода, которая вызывает проблему, поскольку синхронизация позволяет обоим мирам использовать одни и те же буферы. Например
cout << "Hello"; printf("World"); cout << "Ciao";
; без синхронизации никогда не узнаешь, получишь лиHelloCiaoWorld
илиHelloWorldCiao
илиWorldHelloCiao
...tie
позволяет вам иметь гарантию, что каналы ввода-вывода в мире C ++ связаны друг с другом, что означает, например, что каждый вывод был сброшен до того, как происходит ввод (подумайте об этомcout << "What's your name ?"; cin >> name;
).Вы всегда можете смешивать операции ввода-вывода C или C ++, но если вы хотите разумного поведения, вы должны синхронизировать оба мира. Помните, что вообще не рекомендуется смешивать их, если вы программируете на C, используйте C stdio, а если вы программируете на C ++, используйте потоки. Но вы можете смешать существующие библиотеки C с кодом C ++, и в этом случае необходимо синхронизировать оба.
источник
cout <<
не могут изменить порядок, поэтомуCiaoHelloWorld
в вашем примере это невозможно. Синхронизация касается строго различных методов буферизации.Используя
ios_base::sync_with_stdio(false);
достаточно , чтобы отделитьC
иC++
потоки. Вы можете найти обсуждение этого в Стандартных C ++ IOStreams and Locales , написанных Лангером и Крефтом. Они отмечают, что то, как это работает, определяется реализацией.В
cin.tie(NULL)
Вызов , кажется, запрашивающим развязку между деятельностью поcin
иcout
. Я не могу объяснить, почему использование этого с другой оптимизацией должно вызывать сбой. Как уже отмечалось, предоставленная вами ссылка плохая, поэтому здесь нет никаких предположений.источник
Это обычная штука для изготовления cin ускорить ввод .
Для быстрого объяснения: первая строка отключает синхронизацию буфера между потоком cin и инструментами stdio в стиле C (такими как scanf или gets) - поэтому cin работает быстрее, но вы не можете использовать его одновременно с инструментами stdio .
Вторая строка отвязывает cin от cout - по умолчанию буфер cout очищается каждый раз, когда вы читаете что-то из cin . И это может быть медленным, когда вы постоянно читаете что-то маленькое, а затем много раз пишете что-то маленькое. Таким образом, строка отключает эту синхронизацию (буквально привязывая cin к нулю вместо cout ).
источник
Лот отличного ответа. Я просто хочу добавить небольшую заметку о разделении потока .
cin.tie(NULL);
Я столкнулся с проблемой при развязке потока с помощью CodeChef платформой . Когда я отправил свой код, платформа ответила «Неверный ответ», но после привязки потока и тестирования отправки. Это сработало.
Итак, если кто-то хочет отвязать поток, выходной поток должен быть сброшен.
Изменить: я не знаком со всей платформой, но это то, что я испытал.
источник