Язык программирования C++: история, стандарты и первые программы

Рабочее место программиста с открытым редактором кода на мониторе Программирование и разработка

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

Все примеры кода собраны компилятором Clang 21.1 на Windows и запущены, результат скопирован из консоли.

Кто создал язык C++ и как он развивался

Бьёрн Страуструп, датский программист, в 1979 году начал работу над языком «C с классами» в американской исследовательской лаборатории, где до этого появились Unix и язык C. Ему нужно было писать эффективные системные программы в стиле языка Simula 67, и для этого он добавил к C классы, более строгую проверку типов и абстракцию данных. В декабре 1983 года новый язык получил имя C++: ++ в языке C означает операцию увеличения на единицу. В октябре 1985 года вышел первый коммерческий компилятор и одновременно первое издание книги Страуструпа «Язык программирования C++».

Дальше язык развивался через международный стандарт. По датам видно, что после C++11 версии выходят с шагом в три года:

Стандарт Год Что появилось главного
C++98 1998 первый международный стандарт, стандартная библиотека шаблонов (STL)
C++03 2003 исправления C++98, почти без новых возможностей
C++11 2011 auto, лямбды, nullptr, цикл по диапазону, семантика перемещения, потоки, умные указатели
C++14 2014 обобщённые лямбды, make_unique, двоичные литералы
C++17 2017 структурные привязки, if constexpr, optional, string_view, filesystem
C++20 2020 концепты, модули, корутины, диапазоны (ranges), format, оператор <=>
C++23 2024 print, expected, модуль стандартной библиотеки
C++26 работа завершена в 2026 рефлексия на этапе компиляции, контракты, std::execution

У C++23 в таблице 2024 год: технически версию закончили в 2023-м, а опубликован стандарт ISO/IEC 14882:2024 только в октябре 2024 года. Для учёбы в 2026 году мы бы советовали ориентироваться на C++20. GCC поддерживает его почти полностью (модули пока в экспериментальном режиме) и с 16-й версии включает по умолчанию, в Visual Studio ключ /std:c++20 есть с версии 2019 16.11. Возможности C++23 добавляйте по мере того, как они появляются в вашем компиляторе.

Старый компьютерный терминал с зелёным экраном в лаборатории

Где используется язык программирования C++

Язык C++ выбирают там, где важны скорость и контроль над ресурсами компьютера:

  • игровые движки и сами игры: игровые классы в Unreal Engine пишутся на C++;
  • браузеры: Chromium и Firefox;
  • компиляторы и инструменты разработки: на C++ написаны LLVM и Clang, а GCC перешёл на C++ в 2012 году;
  • компоненты операционных систем, например Windows;
  • системы управления базами данных, например сервер MySQL;
  • графические редакторы, например Photoshop.

Для сайтов, анализа данных и скриптов автоматизации обычно берут Python или JavaScript: на них ту же задачу решить проще и быстрее, а скорость C++ там редко нужна.

Первая программа на C++: Hello, World

Классический первый пример выводит строку в консоль:

#include <iostream>

int main() {
    std::cout << "Hello, World!\n";
    return 0;
}

Программа выводит:

Hello, World!

Строка #include <iostream> подключает часть стандартной библиотеки, которая отвечает за ввод и вывод. int main() объявляет главную функцию: с неё начинается выполнение программы, а возвращаемое значение типа int получает операционная система. Тело функции стоит в фигурных скобках. std::cout обозначает поток вывода из пространства имён std, оператор << отправляет в него строку, а return 0; сообщает, что программа завершилась без ошибок. Если return в main не написать, функция всё равно вернёт ноль.

Читайте также:  Строки в PHP: кавычки, echo, функции и работа с UTF-8

В C++23 то же самое можно записать короче, через println. Собирается такой файл с флагом -std=c++23, вывод тот же:

#include <print>

int main() {
    std::println("Hello, World!");
}

Две частые ошибки новичка

Если убрать std:: и написать просто cout, сборка остановится с таким сообщением об ошибке:

err1.cpp:4:5: error: use of undeclared identifier 'cout'
    4 |     cout << "Hello, World!\n";
      |     ^~~~
1 error generated.

Имя cout живёт в пространстве имён std, и без приставки компилятор его не видит. Во многих учебниках встречается строка using namespace std;, которая открывает всё пространство имён сразу. В маленьком учебном файле это работает, но в заголовочных файлах и больших проектах так делать не стоит: имена из стандартной библиотеки начинают конфликтовать с вашими.

Разработчик смотрит на монитор с размытыми красными строками в консоли

Если забыть точку с запятой, сообщение покажет место, где компилятор её ждал:

err2.cpp:4:35: error: expected ';' after expression
    4 |     std::cout << "Hello, World!\n"
      |                                   ^
      |                                   ;

Как код превращается в программу: компиляция

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

  1. Препроцессор подставляет содержимое #include и раскрывает макросы. Пять строк Hello, World после команды clang++ -E hello.cpp превратились у нас в 63 494 строки: столько кода приносит <iostream>.
  2. Компиляция переводит каждый файл .cpp в объектный файл .o: clang++ -c hello.cpp -o hello.o.
  3. Компоновщик (линкер) собирает объектные файлы и библиотеки в один исполняемый файл: clang++ hello.o -o hello.

Обычно все три этапа выполняет одна команда:

g++ -std=c++20 -Wall -Wextra hello.cpp -o hello
./hello

Флаги -Wall -Wextra включают предупреждения. Мы советуем ставить их с первого дня: они ловят неиспользуемые переменные, сравнение знаковых и беззнаковых чисел и другие ошибки до запуска.

Основных компиляторов три, для учёбы все бесплатные: GCC (Linux, на Windows через MinGW), Clang (все платформы, на macOS ставится с Xcode Command Line Tools) и MSVC из Visual Studio Community. Писать код удобно в Visual Studio, VS Code с расширением для C++ или CLion. Чтобы начать без установки, первые программы можно запустить в онлайн-компиляторе прямо в браузере.

Какую версию стандарта использует компилятор

Если флаг -std не указан, компилятор выбирает версию языка сам. Посмотреть её можно через макрос __cplusplus:

#include <iostream>

int main() {
    std::cout << __cplusplus << '\n';
}

Мы собрали этот файл в Clang 21 с разными флагами:

Флаг Вывод программы
-std=c++98 199711
-std=c++11 201103
-std=c++14 201402
-std=c++17 201703
-std=c++20 202002
-std=c++23 202302
без флага 201703

Без флага Clang 21 собирает по C++17, GCC с 11-й по 15-ю версию тоже, а GCC 16 уже по C++20. Visual Studio по умолчанию всегда показывает 199711, даже если проект собирается по C++20. Чтобы макрос показывал настоящую версию, добавьте ключ /Zc:__cplusplus в настройках проекта.

Ноутбук с терминалом, где идёт сборка программы, крупный план клавиатуры

Основы синтаксиса: типы данных, переменные и функции

C++ относится к языкам со статической типизацией: тип каждой переменной известен на этапе компиляции. Базовые типы данных: int для целых чисел, double для дробных, char для символа, bool для логического значения. Строки и динамические массивы берут из стандартной библиотеки: std::string и контейнер std::vector. Вот программа с функциями и вектором:

#include <iostream>
#include <vector>

// Перегрузка функций: одно имя, разные типы параметров
int square(int x) { return x * x; }
double square(double x) { return x * x; }

double average(const std::vector<int>& numbers) {
    if (numbers.empty()) {
        return 0.0;              // пустой вектор: делить на ноль нельзя
    }
    int sum = 0;
    for (int n : numbers) {      // цикл по диапазону, появился в C++11
        sum += n;
    }
    return static_cast<double>(sum) / numbers.size();
}

int main() {
    std::vector<int> scores = {4, 5, 3, 5};

    std::cout << "Среднее: " << average(scores) << '\n';
    std::cout << "Пустой вектор: " << average({}) << '\n';
    std::cout << square(7) << ' ' << square(1.5) << '\n';
}

Программа выводит:

Среднее: 4.25
Пустой вектор: 0
49 2.25

Компилятор выбирает нужную версию square по типу аргумента: для 7 вызывается целочисленная, для 1.5 дробная. Это перегрузка функций. static_cast<double> нужен для приведения типов: без него 17 / 4 дало бы целое 4 вместо 4.25. Параметр const std::vector<int>& передаёт вектор по ссылке, без копирования. Если в консоли Windows вместо русских букв видны непонятные символы, переключите её на UTF-8 командой chcp 65001.

Классы и объекты: объектно-ориентированное программирование в C++

Класс объединяет данные и функции, которые с ними работают. Ниже базовый класс Animal и два наследника, которые по-своему переопределяют виртуальную функцию sound().

Маркерная доска со схемой из прямоугольников и стрелок, рядом ноутбук

#include <iostream>
#include <string>

class Animal {
public:
    Animal(const std::string& name) : name_(name) {}
    virtual ~Animal() { std::cout << "удалён " << name_ << '\n'; }

    virtual std::string sound() const { return "..."; }
    std::string name() const { return name_; }

private:
    std::string name_;   // поле закрыто: снаружи только через name()
};

class Dog : public Animal {
public:
    using Animal::Animal;   // берём конструктор базового класса
    std::string sound() const override { return "Гав"; }
};

class Cat : public Animal {
public:
    using Animal::Animal;
    std::string sound() const override { return "Мяу"; }
};

void speak(const Animal& a) {
    std::cout << a.name() << ": " << a.sound() << '\n';
}

int main() {
    Dog dog("Бобик");
    Cat cat("Мурка");
    speak(dog);
    speak(cat);
    std::cout << "конец main\n";
}   // здесь объекты выходят из области видимости

Программа выводит:

Бобик: Гав
Мурка: Мяу
конец main
удалён Мурка
удалён Бобик

Ключевое слово virtual говорит компилятору выбирать функцию по настоящему классу объекта во время выполнения. Поэтому функция speak, которая принимает ссылку на Animal, получает «Гав» от собаки и «Мяу» от кошки. override просит проверить, что функция действительно переопределяет виртуальную: опечатка в имени или параметрах станет ошибкой компиляции, а не тихим багом. Поле name_ закрыто в секции private, поэтому код снаружи класса может прочитать имя через name(), но изменить его не может.

Читайте также:  Список процессов Linux: как посмотреть запущенные процессы в терминале

Управление памятью и неопределённое поведение

В C++ нет сборщика мусора. Память можно выделять вручную через new и освобождать через delete, но ручное управление памятью легко приводит к утечкам и повторным освобождениям. Современный C++ решает это через RAII: ресурс принадлежит объекту, и деструктор освобождает его сам, когда объект выходит из области видимости. В примере с животными строки «удалён» напечатались после «конец main», в порядке, обратном созданию объектов. Для объектов в куче то же делают умные указатели unique_ptr и shared_ptr.

Модули оперативной памяти на материнской плате, крупный план

Ещё одна ловушка C++ называется неопределённым поведением. Компилятор не обязан проверять, например, выход за границы массива, и файл ниже собирается с -Wall -Wextra без единого предупреждения:

#include <iostream>
#include <stdexcept>
#include <vector>

int main() {
    std::vector<int> v = {10, 20, 30};

    try {
        std::cout << v.at(5) << '\n';     // с проверкой границ
    } catch (const std::out_of_range& e) {
        std::cout << "исключение: " << e.what() << '\n';
    }

    std::cout << v[5] << '\n';            // без проверки: неопределённое поведение
}

У нас программа вывела:

исключение: vector
0

at() проверил индекс и бросил исключение out_of_range, и блок catch его поймал. Оператор [] ничего не проверяет и прочитал чужую память: у нас там оказался ноль. На другой машине там может оказаться мусор, а программа может упасть. В учебном коде пишите at(), пока не привыкнете следить за границами сами.

Современный C++: та же задача в несколько строк

Чтобы вывести квадраты чётных чисел из вектора, по стандарту C++98 писали цикл с итератором и условием внутри. В C++23 хватает диапазонов и println:

#include <print>
#include <ranges>
#include <vector>

int main() {
    std::vector data = {7, 2, 9, 4, 6};

    auto squares = data
        | std::views::filter([](int x) { return x % 2 == 0; })
        | std::views::transform([](int x) { return x * x; });

    std::println("{}", squares);
}

Программа выводит:

[4, 16, 36]

Если собрать тот же файл с -std=c++17, компилятор не найдёт диапазоны:

new23.cpp:9:16: error: no member named 'views' in namespace 'std'

Два монитора рядом с размытым кодом разной длины

В старых учебниках встречается стиль 1990-х: массивы, ручные итераторы, new и delete. Сырой массив, переданный в функцию, не знает своего размера, а каждый забытый delete оставляет утечку (подробнее в разделе об управлении памятью). Старый код по-прежнему компилируется, но начинать лучше с современного: vector, string, умные указатели и алгоритмы стандартной библиотеки.

Читайте также:  Полное руководство по использованию класса Event Trigger в программировании

Плюсы и минусы языка C++

Что даёт язык Чем за это платите
Высокая производительность, близкая к C Долгая компиляция больших проектов
Контроль над ресурсами и железом Неопределённое поведение и утечки, если освобождать ресурсы вручную
Классы, шаблоны, обобщённое программирование Сложность: стандарт C++23 занимает 2104 страницы
Большой набор библиотек и готового кода Много устаревших приёмов в чужом коде и старых книгах
Совместимость с C и старым кодом Нет единого менеджера пакетов, сборку настраивают отдельно (CMake)

C++ и другие языки программирования

C++ C Python Java
Как выполняется компиляция в машинный код компиляция в машинный код интерпретатор байт-код в виртуальной машине
Память вручную или через RAII вручную сборщик мусора сборщик мусора
Классы есть нет есть есть
Типизация статическая статическая динамическая статическая

C++ вырос из C и сохранил почти весь C как подмножество. Строго говоря, C не входит в C++ целиком: есть программы, которые верны на C и не компилируются как C++. Подробно о разнице мы писали в статье чем отличаются C и C++ и что выбрать.

С чего начать изучение языка C++ с нуля

  1. Поставьте компилятор: на Linux g++ из пакетов, на Windows Visual Studio с компонентом «Разработка классических приложений на C++» или MinGW, на macOS Xcode Command Line Tools.
  2. Соберите Hello, World из командной строки, без IDE.
  3. Пройдите переменные, условия и циклы while и for, затем функции и рекурсию.
  4. Освойте vector, string и алгоритмы стандартной библиотеки раньше, чем указатели и new.
  5. Потом классы и объекты, исключения, шаблоны.

Раскрытая толстая книга по программированию рядом с ноутбуком и блокнотом

Из книг для старта подойдёт «Программирование. Принципы и практика с использованием C++» Страуструпа, она рассчитана на новичков без опыта программирования. На русском выходило второе издание (2019) с C++11 и C++14. Третье, 2024 года, построено на C++20 и C++23 и вышло на английском под названием «Programming: Principles and Practice Using C++». Короткий обзор языка для программистов, которые уже пишут на другом, есть в его книге «Язык программирования C++. Краткий курс» (русский перевод 2019 года).

Частые вопросы о языке C++

Подходит ли C++ как первый язык программирования?

Подходит, если вам интересны игры, системное программирование или задачи, где важна скорость. Порог входа выше, чем у Python: больше синтаксиса, нужна сборка, ошибки с указателями не всегда видны сразу. Если цель просто научиться программировать, первый язык лучше взять попроще, например Python.

Нужно ли сначала учить C?

Нет. Современный C++ начинают с vector и string, массивы и malloc можно отложить. Знание C пригодится позже, если придётся работать с прошивками или старым кодом.

Что означают два плюса в названии?

Имя показывает, что язык развился из C постепенно: оператор ++ в C увеличивает значение переменной на единицу. Название C++ впервые использовали в декабре 1983 года.

Какую версию стандарта выбрать в 2026 году?

Берите C++20: собирайте с флагом -std=c++20 (в Visual Studio /std:c++20) и проверьте режим программой с __cplusplus из раздела о версиях стандарта, в GCC и Clang она выведет 202002. В Visual Studio макрос __cplusplus показывает правильное значение только с ключом /Zc:__cplusplus. C++23 включается флагом -std=c++23, если ваш компилятор уже поддерживает нужные части, например println.

Чем C++ отличается от C#?

Это разные языки с похожим названием. C# компилируется в байт-код и работает в среде .NET со сборщиком мусора, C++ компилируется в машинный код и сборщика мусора не имеет.

Оцените статью
bestprogrammer.ru
Добавить комментарий