Первый официальный стандарт C++ появился на свет в 1998 году, спустя почти два десятилетия после создания самого языка Бьярном Страуструпом. Это был важнейший шаг — C++ наконец-то получил чёткую спецификацию, что положило конец "диалектам" компиляторов и упростило жизнь программистов. C++98 ввёл концепции, без которых сейчас трудно представить язык: STL с контейнерами и алгоритмами, шаблоны, исключения, пространства имён, RTTI и механизм приведения типов (cast-операторы). Многие разработчики до сих пор вспоминают, какой революцией стало появление vector<T>, map<K,V> и прочих контейнеров — они избавили нас от необходимости каждый раз изобретать велосипед.
Правда, в первой версии стандарта обнаружились некоторые недочёты и неясности. Исправления дали жизнь минорному обновлению — C++03. Оно не добавило принципиально новой функциональности, но разъяснило некоторые темные места и исправило технические ошибки. Одним из важных изменений стала правка в поведении выражений, содержащих неопределенное поведение во время компиляции.
Несмотря на кажущуюся сейчас примитивность, эти стандарты заложили надежный фундамент для всего, что мы имеем сегодня. Порой я ловлю себя на мысли, что многие молодые разработчики, привыкшие к автоматическому выводу типов и умным указателям, даже не представляют, как выглядел "древний" C++ и через какие тернии прошел язык, чтобы стать таким, каким мы его знаем сейчас.
C++11/14: Революция в языке
Если C++98 заложил фундамент, то C++11 буквально перевернул мир C++ с ног на голову — это была настоящая революция. После долгих 13 лет ожидания (изначально планировавшийся C++0x явно не уложился в сроки десятилетия) язык получил столько нововведений, что многие заговорили о "новом C++".
Главной фишкой C++11 стала автоматическая выводимость типов через ключевое слово auto. Помните эти бесконечные iterator<map<string, vector<int>>::const_iterator it = myMap.begin()? Теперь всё это можно было заменить лаконичным auto it = myMap.begin(). Компилятор сам определял правильный тип, и код становился намного читабельнее. Move-семантика и r-value ссылки произвели настоящий переворот в управлении ресурсами. Теперь можно было "перемещать" тяжелые объекты вместо копирования, что существенно повышало производительность. А универсальная инициализация с фигурными скобками {} наконец-то принесла единообразный синтаксис для создания любых объектов.
Стандартизация многопоточности через библиотеки <thread>, <mutex> и <atomic> избавила разработчиков от необходимости использовать системно-зависимые API или сторонние библиотеки для параллельных вычислений. А nullptr раз и навсегда решил проблемы со старым добрым NULL, который, на минуточку, был просто макросом для нуля.
C++14, вышедший всего через три года, не произвел такого фурора, но добавил множество приятных улучшений: обобщенные лямбды, возвращающие значение auto для функций, расширения для constexpr и другие качественные доработки. Этот стандарт часто называют "малым исправлением C++11".
Вместе эти два стандарта превратили C++ из "C с классами" в мощный современный язык программирования, способный конкурировать по выразительности с функциональными и динамическими языками, сохраняя при этом свою производительность и близость к железу. Одно из самых значимых нововведений C++11 — лямбда-выражения. Впервые в истории языка можно было создавать анонимные функции прямо в месте их использования. Это кардинально изменило подход к написанию алгоритмов и обработке данных. Раньше для использования std::sort с кастомным компаратором приходилось создавать отдельный функтор-класс, теперь же достаточно написать пару строк лямбды.
| C++ | 1
| std::sort(v.begin(), v.end(), [](int a, int b) { return std::abs(a) < std::abs(b); }); |
|
Лямбды вместе с другими улучшениями дали сильный толчок функциональному программированию в C++. Появилась возможность легко комбинировать функции, создавать замыкания, применять функции высшего порядка — словом, использовать приёмы, которые раньше были прерогативой языков вроде Haskell или Lisp.
Ещё одна важная вещь — умные указатели std::unique_ptr, std::shared_ptr и std::weak_ptr. Они наконец-то приручили "ручное" управление памятью в C++, решив проблему утечек и избавив от необходимости явных delete. Появился идиоматичный RAII-подход к управлению всеми ресурсами: "Получил ресурс — упаковал в умный указатель, и больше о нём не думаешь".
| C++ | 1
2
3
4
| void processFile(const std::string& filename) {
auto file = std::make_unique<File>(filename); // Гарантированное освобождение ресурса
// Работа с файлом...
} // file автоматически освобождается здесь |
|
Практика показала, что грамотное использование умных указателей почти полностью устраняет утечки памяти — проблему, десятилетиями преследовавшую C++ разработчиков.
Надо придумать стандарты "Управление кокого либо устройства глазами". Напишите стандарты по вашей фантазии Есть проект "Управления устройства глазами". Пока без реализации. Надо придумать стандарты для него. Ну типа устройства Google Glass например которая... Стандарты JS Разъясните несколько моментов, пожалуйста:
1. ES5 - ES6
(Standart ECMA-262 - это 5 или 6, или от издания зависит? здесь и вообще какие-то... Стандарты СИ Доброе утро, программисты). Ответьте пожалуйста на мои вопросы.
1. Какие стандарты языка СИ существуют?
2. Какой стандарт сейчас принят?
3.... Web стандарты Можете пожалуйста дать ссылку или написать стандарты web? Готовлюсь к экзамену, но в интернете конкретного ничего нет. Везде разные рекомендации, да...
C++17/20: Углубление и расширение возможностей
После поистине революционных C++11/14 комитет по стандартизации не остановился на достигнутом. C++17 продолжил развитие языка, но уже не так радикально — скорее, это было эволюционное развитие. Появились структурированные привязки (structured bindings), позволяющие удобно распаковывать кортежи и пары:
| C++ | 1
| auto [key, value, success] = myMap.try_emplace(key, "value"); |
|
Добавились if constexpr, упрощающий метапрограммирование, и хранилища произвольных типов: std::optional, std::variant и std::any. Библиотека файловой системы std::filesystem наконец-то стандартизировала операции с файлами и каталогами, а параллельные алгоритмы STL автоматически распределяли работу по потокам.
Но настоящий прорыв произошёл с C++20. Этот стандарт добавил несколько фундаментальных возможностей, которые разрабатывались и обсуждались годами. Модули — наконец-то долгожданная замена устаревшему и неэффективному механизму препроцессорных инклудов. Объявляя модуль, мы создаём логическую единицу кода, которая экспортирует только то, что явно разрешено:
| C++ | 1
2
3
4
5
6
7
8
9
10
11
| // math.cppm
export module math;
export int add(int a, int b) { return a + b; }
int helper() { return 42; } // не экспортируется
// main.cpp
import math;
int main() {
int result = add(3, 4); // OK
int h = helper(); // Ошибка: функция не экспортирована
} |
|
Концепты позволили накладывать требования на шаблонные параметры и делать сообщения об ошибках более понятными:
| C++ | 1
2
3
4
5
6
7
8
9
10
11
| template<typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::same_as<T>;
};
template<Addable T>
T sum(std::vector<T> v) {
T result{};
for(auto& element : v) result += element;
return result;
} |
|
Сопрограммы (корутины) принесли в C++ механизм для асинхронного программирования без головной боли с колбэками. А библиотека ranges сделала работу с последовательностями более декларативной и функциональной.
Отдельно стоит отметить преимущество модулей перед заголовочными файлами в плане производительности компиляции. Исследования показали ускорение до 2-5 раз при использовании модулей вместо традиционных инклудов. В чём причина? При подключении заголовочного файла препроцессор каждый раз обрабатывает его содержимое заново, даже если он уже был обработан в другом месте программы. Модули же компилируются однократно и кэшируются, что радикально сокращает время сборки больших проектов.
| C++ | 1
2
3
4
5
6
7
8
| // Традиционный подход с заголовочными файлами
#include <vector>
#include <string>
#include <algorithm>
// Каждый инклуд разворачивается заново
// Модульный подход
import std.core; // Импортируем только один раз всю стандартную библиотеку |
|
В реальном мире переход от заголовочных файлов к модулям может сократить время компиляции крупного проекта с часов до минут, что существенно повышает продуктивность разработчиков.
Концепты же делают шаблонное программирование гораздо более доступным и понятным. Возьмём например классический алгоритм бинарного поиска. Без концептов мы получали крайне запутанные сообщения об ошибках при неправильном использовании:
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| template<typename Container, typename T>
requires std::sortable<typename Container::iterator>
&& std::equality_comparable_with<typename Container::value_type, T>
bool binary_search(const Container& container, const T& value) {
// Реализация безопасна благодаря концептам
auto begin = std::begin(container);
auto end = std::end(container);
while (begin != end) {
auto mid = begin + (end - begin) / 2;
if (*mid == value) return true;
if (*mid < value) begin = mid + 1;
else end = mid;
}
return false;
} |
|
В этом примере концепты гарантируют, что контейнер можно отсортировать, а его элементы сравнивать с искомым значением. Если эти условия не выполняются, компилятор выдаст ясное и понятное сообщение, а не простыню криптографического текста, как раньше.
C++23: Актуальные обновления
После масштабного C++20 следующий стандарт выглядит скромнее, но C++23 добавил немало важных улучшений, которые делают язык ещё более функциональным и удобным. Пожалуй, самое заметное нововведение — библиотека std::expected<T, E>, позволяющая обрабатывать ошибки без исключений:
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| std::expected<int, std::string> divide(int a, int b) {
if (b == 0) {
return std::unexpected("Деление на ноль");
}
return a / b;
}
void process() {
auto result = divide(10, 2);
if (result) {
std::cout << "Результат: " << *result << std::endl;
} else {
std::cout << "Ошибка: " << result.error() << std::endl;
}
} |
|
Этот подход к обработке ошибок напоминает Result из Rust или Either из Haskell и позволяет создавать более предсказуемый и компонуемый код.
Ещё одно долгожданное обновление — поддержка поиска подстрок в строках. Наконец-то не нужно писать
| C++ | 1
| if (s.find("needle") != std::string::npos) |
|
Теперь можно просто:
| C++ | 1
| if (s.contains("needle")) |
|
Казалось бы, мелочь, но как же она раздражала годами!
Для любителей метапрограммирования в C++23 добавлен if consteval, позволяющий определять поведение функции в зависимости от контекста выполнения.
| C++ | 1
2
3
4
5
6
7
| constexpr int get_value() {
if consteval {
return 42; // выполняется в compile-time
} else {
return std::rand(); // выполняется в runtime
}
} |
|
C++23 также продолжает развивать концепцию модулей, добавляя стандартизированные модули для стандартной библиотеки. Важное улучшение для составных паттернов проектирования — расширенные возможности для шаблонной специализации и дедукции типов.
Например, с новым синтаксисом deducing this (неофициально называемым "статическими методами с доступом к this") можно создавать более гибкие интерфейсы для цепочек вызовов:
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
| struct Builder {
template <typename Self>
auto& set_name(this Self&& self, std::string name) {
self.name = std::move(name);
return self;
}
std::string name;
};
// Использование
Builder{}.set_name("test"); |
|
Это упрощает реализацию паттерна Строитель и других составных паттернов, требующих цепочек вызовов с сохранением типа.
Оптимизация кода в C++23 также стала проще благодаря неблокирующим алгоритмам std::execution и новым примитивам синхронизации. Теперь мы можем писать высокопроизводительный многопоточный код с меньшим количеством боли:
| C++ | 1
2
3
4
5
6
7
| std::vector<int> data = {/* большой массив данных */};
std::atomic<int> sum = 0;
std::for_each(std::execution::par_unseq, data.begin(), data.end(),
[&sum](int value) {
sum.fetch_add(value, std::memory_order_relaxed);
}); |
|
C++26: Перспективы и планируемые изменения
Пока сообщество C++ ещё привыкает к новшествам C++23, комитет по стандартизации уже работает над следующей версией языка — C++26. Одно из самых ожидаемых предложений — долгожданная поддержка отражения (reflection). Эта возможность позволит программам анализировать свою собственную структуру в compile-time:
| C++ | 1
2
3
4
5
6
7
8
| // Предполагаемый синтаксис для C++26
template<typename T>
void serialize(const T& obj, Writer& writer) {
// Перебираем все поля класса автоматически
for constexpr(auto member : std::meta::members_of(T)) {
writer.write_field(member.name, member.get(obj));
}
} |
|
Такое отражение радикально упростит создание сериализаторов, ОРМ и других инструментов, которые сейчас требуют утомительного ручного описания структуры классов.
Другая многообещающая функция — паттерн-матчинг, знакомый пользователям Rust и функциональных языков. Он позволит заменить громоздкие условные конструкции элегантным синтаксисом:
| C++ | 1
2
3
4
5
6
7
| std::variant<int, std::string, double> v = 42;
inspect(v) {
<int> i: std::cout << "Целое число: " << i;
<std::string> s: std::cout << "Строка: " << s;
<double> d: std::cout << "С плавающей запятой: " << d;
} |
|
Статические исключения (static exceptions) могут стать ещё одним шагом к безопасному и производительному C++. Они позволят проверять обработку ошибок на этапе компиляции, избегая накладных расходов динамических исключений.
Хотя список предложений для C++26 продолжает расти и изменяться, уже ясно, что этот стандарт сосредоточится на трёх ключевых аспектах: безопасности, производительности и удобстве разработки. Особенно интересны механизмы для лучшей интеграции с современными методами сборки и развёртывания, такими как контейнеры и CI/CD-пайплайны.
Стандарты, переносимость Расскажите поподробнее про код запуска, который компоновщик якобы вставляет в и исполняемый файл. в инете ничего не нарыл. А еще про переносимость... Стандарты CSS Доброй ночи, друзья.
Доделывал проект и в какой раз опять таки задался вопросом стандартами CSS. За ответами решил полезть в Google, но нашёл... Стандарты W3C Многие слышали что-то о стандартах W3C, но где можно о них почитать? Кто знает подскажите плиз! Желательно на русском языке. Устаревшие стандарты Всем доброго вечера!
В ходе пятидневного экспресс-обучения С++ столкнулась с проблемой, которую нужно решить в самые краткие сроки, а именно... Стандарты WIFI Здравствуйте, подскажите где можно найти информацию о хар-ках различных стандартов WIFI? Конкретно интересуют такие параметры как SIFS, DIFS и... Совковые стандарты (ТУ)? Кто знаком со справочниками по совковым стандартам (ТУ)? В первую очередь трансформаторов и дросселей, далее - со всеми остановками.
Обозначаемым,... Стандарты SQL Объясните, как реализуются стандарты SQL. Сейчас, как я понял, действует стандарт SQL:2003. Это значит, что все современные СУБД должны его... Стандарты IEC? Добрый день. Нужны стандарты 62052-11, 62053-21, 62053-22, 62053-23. Где их можно найти и скачать? Я искал в гугле и нашёл только оглавление (см.... Стандарты. расшифровка ITIL, PMI PMBOK, SEEK, ISO/IEC TR 16326:1999, ISO/IEC 12207, SWEBOK.
Хочу прочитать про SEEK, но так как это популярное слово, трудно найти. Никто... Стандарты RFC Дайте пожалуйста более подробную информацию о стандарте RFC1123
Точнее как правильно сформировать дату по этому стандарту.
Я так понимаю в... Региональные стандарты Добрый день,
Пытаюсь изменить формат даты и времени для Английского языка на yyyy-MM-dd. Нажимаю применить, все работает дата отображается... ГОСТ Стандарты Здравствуйте!
Срочно по работе понадобились стандарты ГОСТ на английском языке.
А именно ГОСТ 19.ххх-хх
Скажите, может у кого есть или знаете...
|