Термин «современный C++» часто используется как синоним выражения «код, использующий новый стандарт C++». Здесь «новый» может означать что угодно от C++11 до C++17, или даже то, что уже сейчас доступно из C++20. Я думаю, что современный C++ — это нечто большее, не ограничивающееся добавлением флага -std=c++17.

Что значит «современный»?


Если поискать значение слова «современный» в сети, одним из первых мы найдем определение из словаря Merriam-Webster. Вот две части, относящиеся к C++:

[...]

2: involving recent techniques, methods, or ideas: (up-to-date) modern methods of communication

3 capitalized: of, relating to, or having the characteristics of the present or most recent period of development of a language — Modern English

[...]

Техники, методы и идеи имеют отношение к чему-то большему, чем просто новые возможности языка. Часто эти новые возможности поддерживают или включают новые техники, но многие из них существовали уже достаточно долгое время. Что касается характеристик развития языка, в их основе лежит то, как мы используем язык. Это относится к тому, как мы комбинируем старые и новые возможности, и это нечто большее, чем просто рабочая программа на C++, или то, что включено в стандартную библиотеку.

Можно поспорить, что возможности, существовавшие со времен C++98, не входят в современный C++, потому что они существуют слишком давно. Однако, нужно помнить, что самые активные люди в сообществе, которые говорят или пишут о «современном C++», это чаще всего первопроходцы. Большинство использует, изучает и даже преподает старый добрый «C с классами» из 90-х, что делает многие методы, которые там не используются, частью современного C++.

Помимо новых возможностей


Что же из доступного в C++98 я считаю принадлежащим к категории «современный C++»? Вот неполный список некоторых важных возможностей и идей:

RAII


RAII расшифровывается как «получение ресурса есть инициализация», или «получение ответственности есть инициализация». Хотя название делает упор на «инициализацию», ключевая часть здесь, на самом деле — это деструктор. Детерминированное освобождение ресурсов — одна из основных характеристик C++, которая отличает его от большинства других языков. Для многих — это самая важная характеристика.

RAII может использоваться для надежного управления многими вещами, такими как память (например, std::vector, std::string), дескрипторы файлов (std::fstream), сетевые соединения, мьютексы, соединения с базами данных, а также сущности, которые имеют отдаленное отношение к ресурсам. Если вам нужен надежный способ сделать некоторое действие, а потом отменить его на выходе из некоторой области видимости или при уничтожении объекта, RAII — то, что вам нужно.

Я видел много кода, в котором ручная чистка при завершении функций превращалась в кошмар. В случае исключений такая очистка не происходит, так что в этой ситуации RAII — то, что вам нужно. Даже если вы не используете исключения, досрочный выход из функций может существенно улучшить ваш код, но только если вам не нужно проводить чистку.

Определенно, техника RAII входит в современный C++, хотя она и была доступна с самого начала.

Строгая типизация


Идея строгой типизации очень популярна в последнее время. В прошлом любые идентификаторы, размеры, почтовые индексы, цены и так далее представлялись через int или double, или другой арифметический тип. То, что они были совместимы, совершенно несвязанные друг с другом значения, которые по чистой случайности имеют один тип, было источником багов, но что поделать? По крайней мере, компилятор молча не преобразует числа и массивы в строки!

На деле получается, что система типов C++ и абстракции с нулевой стоимостью*, которые предоставляет нам компилятор, позволяют сделать многое. Просто создайте разные типы для идентификаторов, почтовых индексов, размеров (нет, без typedef, спасибо) и так далее. Если вам интересно, посмотрите один из докладов Bjorn Fahller, Jonathan Boccara или Jonathan Muller.

*(Даже если стоимость абстракции ненулевая, докажите, что она неприемлема прежде чем отказываться от нее)

Если не считать некоторых недавних дополнений, <algorithm> был в стандартной библиотеке с самого начала. Но если взглянуть на код, выходит, что люди часто предпочитают писать циклы вручную. Причины разнятся от незнания того, какие стандартные алгоритмы доступны, до веры в то, что «шаблоны слишком медленные» (часто без объяснения, по сравнению с чем).

Программирование этапа компиляции


Вещи вроде метапрограммирования с использованием шаблонов применялись со времен C++98. Логика, выполняемая на этапе компиляции, может существенно уменьшить сложность на этапе выполнения. В прошлом ее было неудобно использовать. Синтаксис шаблонов отличается в сторону усложнения от возможностей, которые есть в последних стандартах. Это что-то вроде отдельного языка, который нам приходится учить. Однако, такие вещи как диспетчеризация тегов или типажи не слишком сложны для использования и написания.

Да, большинство типажей в стандартной библиотеке появилось с приходом C++11, но писать их под свои нужды не слишком сложно, и некоторые наиболее общие из них были в Boost до C++11. Я считаю использование логики этапа компиляции частью современного C++, потому что оно отделяет C++ от вездесущего «C с классами».

Заключение


Современный C++ имеет отношение не к новым стандартам, а к тому, как мы пишем наши программы. Во-первых, на C++98 можно писать в более или менее современном стиле. Во-вторых, «C с классами и range-based for циклами» — это еще не современный C++. Новые возможности языка и библиотек помогают нам писать в стиле современного C++, но не они делают наш код современным C++.

Комментарии (22)


  1. datacompboy
    13.11.2018 21:46
    +13

    Как-то посыла статьи не понял. Как реферат второго курса прочитал O_O

    p.s.: я даже второй раз перечитал. всё равно не дошла радиограмма из центра.


    1. mapron
      13.11.2018 22:13

      Что-то ощущение, как будто какой-то тизер статьи прочитал… наверное 1 или 2 случай, когда в блоге PVS ставлю минус =(

      недавно смотрел доклад с cppcon, один из слайдов был «а что ж такое этот самый modern C++», ощущение что вот просто оттуда все взято.


      1. Andrey2008 Автор
        13.11.2018 22:31
        +6

        Автор (обращаю внимание, что это перевод), хотел на мой взгляд донести мысль, что использовать свежий C++ компилятор и, скажем auto, не означает, что вы пишете на современном языке С++. Можно, например, по-прежнему обрабатывать ошибки и чистить ресурсы написанием goto для перехода к эпилогу функции.

        Возможно, заметка получилась у автора не очень. Ну или перевод не получился :). Но мне мысль хорошо понятна и показалась мне интересной.


        1. mapron
          14.11.2018 10:30
          +3

          Да вроде вы пишете (и автор) правильные вещи. Но это мое мнение — это все не стоит статьи.
          То что не заметил что перевод — целиком мой косяк, каюсь, претензии безосновательны — уж больно не ожидал увидеть перевод в этом блоге =)
          Перевод с точки зрения сохранения смысла хороший. Но сам материал не стоящий. Вот так, уж простите.


  1. degs
    13.11.2018 21:57
    +1

    Большинство дополнений предлагаемых в новых стандартах возникло не на пустом месте, это ответ на запросы программистов улучшить что-то или сделать удобнее. Поэтому выход каждого нового стандарта сопровождается дружным выдохом, «наконец-то, теперь я могу сделать вот так ...». Те же, кто [добровольно] продолжает писать в рамках С++-98 неизбежно упускают какие-то возможности. Я не верю что [нормальный] программист может просто игнорировать способ сделать что-то лучше.
    Обратное разумеется тоже верно, игнорируя, например RAII, нереально писать хорошо на любой версии С++


  1. masb
    13.11.2018 22:36

    Какой C++ начинать учить в конце 2018 начале 2019, при условии что Си в достаточной мере освоен? Желательно с ссылками на материалы/книги.


    1. AlePil
      14.11.2018 02:14
      +1

      C тут не очень-то причём, но в любом случае попробуйте вот с этого


    1. konshyn
      14.11.2018 08:31

      C++98 и С++11, и С++20, другими словами — весь:)

      Книги


    1. DelightfullyBitchySweets
      14.11.2018 09:23
      +1

      Моё, сугубо личное, мнение: С++17 + STL
      Скидую то, что сам читал

      www.piter.com/collection/yazyk-programmirovaniya-ss-s/product/s17-stl-standartnaya-biblioteka-shablonov
      OR
      Осваиваем C++17 STL от ДМК Пресс

      www.piter.com/collection/yazyk-programmirovaniya-ss-s/product/obektno-orientirovannoe-programmirovanie-v-s-klassika-computer-science-3

      А деле как пойдет, там уже надо самому смотреть что больше надо.


      1. tangro
        14.11.2018 13:14
        +1

        С++17 + STL

        Например банальный метод «contains» добавили в std::set только в С++20. А без этого был либо позорный визуально «find() != end()» либо уродливый принципиально count() != 0. Так что нет предела совершенству.


        1. sanyaschet
          14.11.2018 16:37

          if (set.count(elem))
          {
          }
          не так уж уродливо, по сути также с точки зрения интерфейса, за исключением названия


          1. tangro
            14.11.2018 17:32

            Неявный каст числа к булу. Плюс count не обязан работать для set за разумное время (реализация может быть даже за O(n)), в то время как contains будет гарантированно правильным и быстрым.


        1. DelightfullyBitchySweets
          14.11.2018 17:26

          Я с Вами полностью согласен, но как по мне начинать учить с С++20 не стоит.
          Во первых, стандарт еще не вышел, и никто не знает когда выйдет.
          Во вторых, С++17 сейчас флагман, и на нем можно нормально писать что угодно, и нету смыска, как по мне, начинать учить С++20 новичку без нормальной литературы.

          Человек просил посоветовать литературу, а по С++20, насколько я знаю, нету полноценых изданий тот O'Reilly например.


        1. dipsy
          14.11.2018 17:57
          +1

          Я себе ещё в С++98 почти сразу добавил самописный bool contains(const set«T»&, T), и не очень понимаю зачем писать раз за разом уродливые конструкции, если можно их заменить более красивыми (лаконичными), которые можно сделать в рамках любого диалекта языка.


    1. Gorthauer87
      14.11.2018 16:41

      Rust же.


  1. AlePil
    14.11.2018 02:14

    1. AlePil
      14.11.2018 02:16
      +1

      masb очень странно все-таки работает мобильная версия, но ссылка для Вас


    1. mapron
      14.11.2018 13:25

      Мое личное мнение (как человека, начавшего изучение С++ именно с С) — это неудачный совет. Страуструп хорош, как фундаментальный учебник для человека, замечателен как справочник, как настольная книга, когда начинаешь курить новые конструкции.
      Но вот прям как самоучитель для начинающих… увольте. Мне кажется, должны быть альтернативы получше, иначе если не зайдет, у человека вообще может желание изучать язык отбить.


  1. Antervis
    14.11.2018 14:11
    +3

    в начале прочтения статьи у меня было чувство что дальше по тексту будут примеры как делать не надо, какие конструкции лучше заменять какими в «современном с++», другими словами, больше конкретики. И тут внезапно статья оборвалась…


    1. khim
      14.11.2018 20:51

      Угу. Читаешь так — да, введение хорошее, часто про него забывают, приятно, что кто-то потратил на это время, а не «с места в карьер», ща заценим саму статью… ой, а где же она?

      Любая статья выигрывает от хорошей преамбулы, но когда кроме введения ничего нет… возникает ощущение недоумения…


  1. Eagle_NN
    14.11.2018 14:57
    +1

    Статья ни о чем.
    Использована куча терминов с пояснениями что это такое, однако никаких ссылок на то, какое отношение они имеют в С++ нет.
    Встречаются упоминания разных стандартов С++, однако без конкретики это тоже ни о чем.

    Хотелось бы в такой статье видеть примеры как:
    в C++98 конструкцию «ХХХХХХ» реализовать было сложно «пример кода С++98», а в C++17 реализуется легко «пример кода С++17»


    1. kovserg
      14.11.2018 18:51
      +2

      «Настоящий физик может писать фортраном на любом языке»

      Как теперь в современном C++ получают указатель на член класса?
      Как обстоят дела с экспортом функционала во внешний мир?
      Уже сделали препроцессор удобным и безопасным?
      Сколько нынче весит C++ компилятор со стандартной библиотекой?
      Есть ли уже стандартный менеджер пакетов и зависимостей?