Поделиться через


Возвращение к C++ (современный C++)

C++ является одним из наиболее широко используемых языков программирования в мире. Грамотно сконструированные программы на языках C++ быстры и эффективны. Язык является более гибким, чем другие языки, поскольку его можно использовать для создания широкого спектра приложений — от интересных и ярких игр до высокопроизводительного научного программного обеспечения и драйверов устройств, внедренных приложений и клиентских приложений Windows. Более 20 лет C++ используется для решения подобных и многих других задач. Возможно, вы не знаете, что все больше программистов С++ отказались от программирования вчерашнего дня в C-стиле и перешли к современной модели программирования С++.

Одно из начальных требований для C++ — обратная совместимость с языком C. С этого момента язык C++ эволюционировал через несколько итераций — C с классами, исходная спецификация языка C++ и множество последовательных усовершенствований. Из-за этого наследия C++ часто называют мультипарадигматическим языком программирования. В C++ доступны чисто процедурное программирование в C-стиле, которое содержит необработанные указатели, массивы, строки с конечным символом null, пользовательские структуры данных и другие компоненты, которые могут обеспечить высокую производительность или стать причиной ошибок и чрезмерной сложности кода. Поскольку программирование в стиле языка C чревато подобными опасностями, одной из основных целей создания C++ было сделать программы как типобезопасными, так и более простыми в написании, расширении и сопровождении. Уже на ранних этапах развития в языке C++ были полностью реализованы такие парадигмы программирования, как объектно-ориентированное программирование. С годами к этому языку были добавлены функции и стандартные библиотеки структур данных и алгоритмов, прошедшие тщательное тестирование. Именно благодаря этим дополнениям появился и существует современный стиль C++.

Современный язык C++ обеспечивает следующие возможности:

  • Область стека вместо кучи или статической глобальной области.

  • Автоматическое определение типа вместо явных имен типов.

  • Интеллектуальные указатели вместо необработанных указателей.

  • Типы std::string и std::wstring (см. <string>) вместо необработанных массивов char[].

  • Стандартная библиотека шаблонов (STL) содержит такие контейнеры как vector, list и map, а не необработанные массивы пользовательских контейнеров. См. <vector>, <list> и <map>.

  • Алгоритмы STL вместо закодированных вручную.

  • Исключения для сообщения о состояниях ошибки и их обработки.

  • Свободное от блокировок взаимодействие между потоками с помощью STL std::atomic<> (см. <atomic>) вместо других механизмов взаимодействия между потоками.

  • Встроенные лямбда-функции вместо небольших функций, реализованных отдельно.

  • Конструкции на основе диапазонов для циклов, позволяющие создавать более надежные циклы, которые работают с массивами, контейнерами STL и коллекциями Среда выполнения Windows в форме for ( for-range-declaration : expression ). Это часть базовой языковой поддержки. Для получения дополнительной информации см. Основанное на диапазоне выражение for (C++).

Сам язык C++ также развивался. Сравните следующие фрагменты кода. Этот фрагмент показывает, как обстояли дела в C++ раньше:

// circle and shape are user-defined types
circle* p = new circle( 42 ); 
vector<shape*> v = load_shapes();

for( vector<circle*>::iterator i = v.begin(); i != v.end(); ++i ) {
    if( *i && **i == *p )
        cout << **i << “ is a match\n”;
}

for( vector<circle*>::iterator i = v.begin();
        i != v.end(); ++i ) {
    delete *i; // not exception safe
}

delete p;

А этот фрагмент показывает, как та же задача решается в C++ сейчас:

#include <memory>
#include <vector>
// ...
// circle and shape are user-defined types
auto p = make_shared<circle>( 42 );
vector<shared_ptr<shape>> v = load_shapes();

for_each( begin(v), end(v), [&]( const shared_ptr<shape>& s ) {
    if( s && *s == *p )
        cout << *s << " is a match\n";
} );

В современном C++ не следует использовать операторы new и delete или явную обработку исключений, поскольку вместо этого можно использовать интеллектуальные указатели. При использовании вычета типа auto и лямбда-функции можно написать код быстрее, сделать его более сжатым и понятным. Кроме того, цикл for_each проще и удобнее в использовании, а также в меньшей степени подвержен непреднамеренным ошибкам, чем цикл for. Можно использовать для написания приложения стандартный текст и минимум строк кода. Кроме того, этот код можно сделать безопасным в отношении исключений и в отношении памяти, исключая необходимости обрабатывать выделение и освобождение или коды ошибок.

Современный C++ включает два типа полиморфизма: во время компиляции, с помощью шаблонов, и в среде выполнения, путем наследования и виртуализации. В целях повышения эффективности можно объединить два типа полиморфизма. Шаблон STL shared_ptr использует внутренние виртуальные методы для выполнения удалений без усилий. Однако не злоупотребляйте виртуализацией для полиморфизма, если лучше использовать шаблон. Шаблоны могут быть очень мощными.

Если вы начинаете работать с С++ после другого языка, особенно после управляемого языка, в котором большинство типов — ссылочные типы, и лишь немногие — типы значений, знайте, что классы С++ — это типы значений по умолчанию. Однако можно указывать их как ссылочные типы для получения полиморфного поведения, которое соответствует концепции объектно-ориентированного программирования. Удобно представлять это себе так: типы значений относятся, скорее, к управлению памятью и макетом, ссылочные типы относятся, скорее, к базовым классам и виртуальным функциям для поддержки полиморфизма. По умолчанию типы значений являются копируемыми — каждый из них имеет конструктор копии и оператор присваивания копированием. При определении ссылочного типа сделайте класс недоступным для копирования, отключив конструктор копий или оператор назначения копирования и воспользовавшись виртуальным деструктором, поддерживающим полиморфизм. Типы значений также связаны с содержимым, то есть, если они копируются, необходимо предоставить два независимых значения, которые можно изменить по отдельности. Однако ссылочные типы, скорее, связаны с идентификацией — какой это объект — и иногда из-за этого называются полиморфными типами.

C++ переживает возрождение, потому что мощность снова становится приоритетом. Языки, например Java и C#, хорошо подходят, если важна продуктивность программиста, однако как только речь заходит о мощности и производительности, становятся очевидными их ограничения. Для повышения эффективности и мощности, особенно для устройств с ограниченным оборудованием, ничто не подходит лучше, чем современный С++.

Современен не только язык, но и средства разработки. Visual Studio делает все части цикла разработки надежными и эффективными. Он включает средства управления жизненным циклом приложения (ALM), усовершенствования интегрированной среды разработки, такие как IntelliSense, совместимые со средствами механизмы, такие как XAML, а также сборки, отладки и многие другие средства.

Статьи в этом разделе документации содержат общие правила и рекомендации по наиболее важным функциям и методам для записи современных программ на языке C++.

Подробнее см. в следующей статье на сайте StackOverflow: Какие идиомы C++ не рекомендуется использовать в C++11

См. также

Ссылки

Лямбда-выражения в C++

Другие ресурсы

Справочник по языку C++

Справочник по стандартной библиотеке C++