Зверь ревет в ответ: возрождение C++
Введение
С момента своего создания в 1979 году как C with Classes C++ превратился в мощный инструмент для миллионов разработчиков программного обеспечения по всему миру. . Согласно опросу, проведенному JetBrains в 2015 году, по всему миру насчитывалось около 4,4 миллиона разработчиков C++. За свою долгую и зачастую бурную историю язык пережил немало взлетов и падений. Он постоянно пытался отразить многочисленные обвинения, выдвигаемые против него, например, в том, что это чрезвычайно сложный и пугающий язык для изучения. В недавней истории другие языки, которые считаются менее сложными и более легкими для изучения, обогнали C++ по популярности в кругах программистов. Одним из таких языков является Java. С момента своего объявления в 1995 году Java покорила сообщество программистов благодаря тому, что она была гораздо более дружелюбна к новичкам. Кроме того, программы, написанные на Java, должны были работать поверх JVM, что делало программы на Java очень переносимыми, в отличие от программ на C++.
Несмотря на свое мрачное прошлое, для C++ еще не все потеряно. Этот язык по-прежнему является наиболее предпочтительным для написания приложений, где производительность является наиболее важным фактором. Примеры таких приложений включают:
- Поисковые системы в Интернете (например, Google)
- Механизмы веб-браузера (например, Mozilla Firefox)
- Системное программное обеспечение (например, операционные системы и драйверы устройств)
- Разработка игр
- Программное обеспечение телекоммуникационных систем.
Полный список приложений, написанных с использованием C++, можно найти по этой ссылке, поддерживаемой Бьерном Страуструпом (создателем языка).
Зверь ревет назад
Как объясняется в небольшой книжке C++ Today, опубликованной O'Reilly, распространение мобильных устройств и развитие облачных вычислений вернули вопрос производительности к центральная сцена. По словам авторов книги, производительность на ватт в настоящее время является одним из наиболее важных факторов, влияющих на мобильные устройства. То же самое относится и к облачным компьютерам, которые работают в облачных центрах обработки данных. Эти факторы привели к возрождению интереса к C++ со стороны более широкого сообщества разработчиков.
Чтобы лучше обслуживать новый легион инженеров-программистов, заинтересованных в этом языке, C++ пришлось претерпеть огромные изменения. Изменения были направлены на то, чтобы сделать язык более доступным и менее сложным. Кроме того, в язык были включены новые функции (например, возможности многопоточности и лямбда-выражения), чтобы сделать его более современным.
Такие усилия, направленные на то, чтобы снова сделать C++ популярным, напрямую привели к тому, что теперь широко известно как «Современный C++». Начиная с C++11, в язык было добавлено множество новых отличных функций, что привело к новому виду, которого так жаждало большинство разработчиков. C++14 считался небольшим отладочным выпуском, в то время как в C++17 было добавлено несколько дополнительных функций. язык.
Далее следует краткое обсуждение некоторых новых функций C++, начиная с C++11.
Введите вывод, используя ключевое слово ‘auto’
Вывод типа (или дедукция) является функцией по умолчанию в большинстве современных языков программирования. Например, объявление переменной в Go выглядит так:
x := 10 // x inferred as an integer
Как видно из фрагмента кода, вам не нужно явно объявлять тип переменной «x». Вместо этого компилятор Go сделает это за вас, основываясь на заданном начальном значении.
В «старом» C++ (pre-C++11) тип переменной нужно было объявлять явно, например так:
int x; // x declared as an integer
int y = 10; // y declared and initialized at the same time
Начиная с C++11 теперь можно использовать вывод типа с помощью ключевого слова auto
, как показано ниже:
auto x = 1; // x deduced as an integer
Обратите внимание, что для работы вывода типа переменная должна быть инициализирована.
for
Цикл на основе диапазона
Эта функция делает написание циклов for
более лаконичным и увлекательным.
В Python цикл for
на основе диапазона выглядит так:
for i in range(10):
print(i)
Вывод кода выше:
0
1
2
3
4
5
6
7
8
9
Чтобы добиться аналогичного результата, используя старый код C++, нам пришлось бы написать что-то вроде этого:
// declare and initialize an array of integers
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for ( int i = 0; i < 10; ++i ) {
cout << a[i] << endl;
}
Используя цикл for
на основе диапазона, приведенный выше код можно переписать, как показано ниже:
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for ( int i : a ) {
cout << i << endl;
}
Гораздо лучше и чище, вам не кажется?
Чтобы лучше проиллюстрировать преимущества ключевого слова auto
и цикла for
loop на основе диапазона, вот еще один пример:
Эта первая версия написана в старом стиле C++.
#include <iostream>
#include <vector>
using namespace std;
int main( int argc, char ** argv ) {
// Declare and initialize a vector of integers
vector<int> vi = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Declare an iterator and loop through
// all the vector elements
for( vector<int>::iterator it = vi.begin(); it < vi.end(); ++it ) {
cout << *it << endl;
}
return 0;
}
Ниже представлена вторая версия с использованием ключевого слова auto
:
#include <iostream>
#include <vector>
using namespace std;
int main( int argc, char ** argv ) {
// Declare and initialize a vector of integers
vector<int> vi = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Type deduction using auto
for( auto it = vi.begin(); it < vi.end(); ++it ) {
cout << *it << endl;
}
return 0;
}
Обратите внимание, что теперь нам больше не нужно объявлять тип it
в качестве векторного итератора.
Третья версия еще короче и лаконичнее. Здесь мы используем основанный на диапазоне for
loop:
#include <iostream>
#include <vector>
using namespace std;
int main( int argc, char ** argv ) {
// Declare and initialize a vector of integers
vector<int> vi = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Range-based for loop
for ( auto & i : vi ) {
cout << i << endl;
}
return 0;
}
Вывод для кода выше будет:
1
2
3
4
5
6
7
8
9
10
Auto
в шаблонах
Это функция C++17, которая теперь позволяет объявлять нетиповые аргументы шаблона с помощью ключевого слова auto
. Это позволяет выводить параметры шаблона в момент создания экземпляра, а не указывать их явно, как показано ниже:
template <auto V> void somefunc() { } // V is some constant (const) value
somefunc<20>(); // 'int' is deduced
Раньше вам нужно было написать что-то вроде этого:
template <typename T, V> void somefunc() { }
somefunc<int, 20>();
if constexpr (выражение)
Это еще одна новая функция в C++17, которую можно рассматривать как версию C++ времени компиляции if
.
Это позволяет компилировать блоки кода, только если constexpr
оценивается как true
во время компиляции:
if constexpr(is_integer ...) { // execute integerstuff }
else if constexpr(is_floating_point ...) { // execute floatingpointstuff }
else { // NaN; }
Для получения дополнительной информации о многих других новых функциях C++ перейдите по этой ссылке, поддерживаемой Standard C++ Foundation (isocpp.org).
Два самых популярных проекта, выполненных с использованием современного C++:
- Seastar: платформа C++ с открытым исходным кодом для высокопроизводительных серверных приложений, которая составляет основу ScyllaDB, базы данных NoSQL, которую рекламируют как Cassandra следующего поколения.
- OSv: облачная операционная система, полностью написанная на C++.
Вывод
Так же, как часто говорят, что Лев никогда не спит, C++ никогда не спит. И как только мы подумали, что зверь задремал, он взревел в ответ, ко всеобщему удовольствию (и удивлению!)
Использованная литература:
- C++ сегодня: крошечная бесплатная электронная книга (74 страницы) Джона Калба и Гаспера Азмана.
- Эффективный современный C++: книга Скотта Мейерса.