Недавно в олимпиадном программировании я перешёл с Pascal на C++. Это был приятный переход и я не жалею о нём, мне открылось множество стандартных решений с готовыми методами и сущностями, которые раньше приходилось реализовывать самостоятельно. Потребовалось всего лишь выучить особенности нового синтаксиса и научиться ориентироваться в стандартной библиотеке.

Некогда я слышал следующую фразу:

В C++ существует одно и только одно решение данной задачи.

Имея совсем небольшой опыт, могу всё же заявить, что в C++ существует как минимум 3 (три) решения любой задачи:

  • Стандартная библиотека C++
  • Стандартная библиотека C. Была оставлена для совместимости, иногда бывает полезна, но лично я стараюсь избегать её, так как считаю, что это излишне. В стандартной библиотеке C++ перереализовано всё из стандартной библиотеки C и чуть больше с учётом современных требований: скорость и безопасность.
  • Самописные решения

Самое явное влияние этого «правила трёх решений» я испытал при работе с файловым вводом-выводом. Существует множество методов работы с файлами в C++. В данной статье я проанализирую лишь те из них, которые разумно применять в олимпиадном программировании: быстро написать, не подключать ничего извне. Эти методы:

  • «Консервативный» freopen из C
    • Ввод-вывод через стандартные объекты cin, cout
      • Включенная синхронизация
      • Выключенная синхронизация
    • Ввод-вывод через функции printf, scanf
      • Включенная синхронизация
      • Выключенная синхронизация
  • «Современный» fstream из C++

Задача: прочитать 10 000 000 1 000 000 чисел из файла in.txt, записать те же числа в файл out.txt.

Условия: «подвальные». Тестирование на слабой виртуальной машине, в качестве результатов приведу время выполнения. Для повышения точности проведу по 10 5 3 теста для каждого решения, результат усредню.


  • freopen через cin, cout с синхронизацией и без — 76 секунд в среднем. Мораль: не стоит мешать файловый ввод-вывод C и C++.
  • freopen через scanf, printf с синхронизацией — 1.761 секунды, без — 1.736 секунды.
  • fstream — 1.602 секунды, рекорд. Хоть отрыв и не большой, но приятно, ведь сам я пользуюсь именно этим методом (результаты не подтасовывал).

Итоги:

  • Смешение стандартных потоков C и C++ — очень плохая практика
  • В критичных ситуациях лучше отключать синхронизацию. Касается работы с исключительным C-подходом, при смешенном подходе время уже не важно (76 секунд…), а fstream не имеет пары для синхронизации, следовательно, там её вообще нет.

Также про другие методы работы с файлами можно почитать здесь: http://habrahabr.ru/post/246257/