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

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

1. Введение в C++: структура программы, типы данных и операции ввода-вывода

Введение в C++: структура программы, типы данных и операции ввода-вывода

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

В этой первой статье мы разберем фундамент: как выглядит минимальная программа, как компьютер хранит данные и как научить программу общаться с пользователем.

Структура программы на C++

Любое путешествие начинается с первого шага, а в программировании — с программы «Hello, World!». Давайте посмотрим на классический пример кода, который просто выводит текст на экран, и разберем его по косточкам.

На первый взгляд это может показаться набором заклинаний. Давайте расшифруем каждую строку.

1. Директивы препроцессора

Строка #include <iostream> — это инструкция для препроцессора. Она говорит компилятору: «Прежде чем собирать программу, подключи сюда содержимое файла iostream».

* i (input) — ввод * o (output) — вывод * stream — поток

Без этой строки мы не смогли бы ничего вывести на экран или считать с клавиатуры.

2. Функция main

Строка int main() { ... } — это сердце вашей программы. Любая программа на C++ начинает свое выполнение именно с функции main.

* int означает, что функция должна вернуть целое число (integer) по завершении работы. * Фигурные скобки { и } обозначают начало и конец тела функции — блока, где находятся инструкции.

!Анатомия базовой программы на C++

3. Вывод текста

Инструкция std::cout << "Hello, World!" << std::endl; делает всю видимую работу.

* std — это пространство имен (стандартная библиотека). Это как фамилия для функций, чтобы не путать их с чужими. * cout (character output) — объект, отвечающий за вывод на экран. * << — оператор вставки. Представьте, что это стрелочки, которые направляют строку "Hello, World!" прямо в поток вывода cout. * endl (end line) — переносит курсор на новую строку. * Точка с запятой (;) — это, пожалуй, самый важный знак препинания. В C++ каждая команда должна заканчиваться точкой с запятой. Забытая ; — самая частая ошибка новичков.

4. Завершение программы

Строка return 0; сообщает операционной системе, что программа завершилась успешно. Если бы мы вернули другое число (например, -1), это сигнализировало бы об ошибке.

Переменные и типы данных

Программы редко просто выводят текст. Обычно они обрабатывают данные. Для хранения данных в памяти компьютера используются переменные.

Представьте, что переменная — это коробка. Чтобы пользоваться коробкой, вы должны:

  • Дать ей имя (название переменной).
  • Сказать, что именно в ней будет храниться (тип данных).
  • В C++ строгая типизация. Это значит, что если вы создали коробку для обуви (целых чисел), вы не можете положить туда суп (дробное число или текст) без специальных преобразований.

    Основные типы данных

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

    | Тип данных | Описание | Пример значения | Размер в памяти (обычно) | | :--- | :--- | :--- | :--- | | int | Целые числа (Integer) | 42, -10, 0 | 4 байта | | double | Дробные числа двойной точности | 3.14, -0.001 | 8 байт | | char | Одиночный символ (Character) | 'A', 'z', '!' | 1 байт | | bool | Логический тип (Boolean) | true, false | 1 байт | | std::string | Строка текста (требует #include <string>) | "Привет" | Зависит от длины |

    Объявление и инициализация

    Создать переменную можно так:

    > Важно: Имена переменных должны быть понятными. Лучше написать appleCount, чем просто a. Имя не может начинаться с цифры и не должно содержать пробелов.

    Операции ввода и вывода

    Мы уже знакомы с std::cout для вывода. Теперь научимся получать данные от пользователя с помощью std::cin.

    Ввод данных (cin)

    cin (character input) работает в паре с оператором извлечения >>. Обратите внимание: стрелочки направлены в другую сторону, показывая, что данные идут из клавиатуры в переменную.

    Пример программы, которая знакомится с пользователем:

    !Потоки ввода и вывода данных в C++

    Особенности ввода

    Команда std::cin считывает данные до первого пробела. Если вы введете имя «Иван Иванович», в переменную name попадет только «Иван». Для чтения целой строки с пробелами используется функция std::getline(std::cin, name), но об этом мы поговорим в следующих статьях.

    Арифметические операции

    C++ отлично справляется с математикой. Основные операторы интуитивно понятны:

    * + (сложение) * - (вычитание) (умножение) * / (деление) * % (остаток от деления — только для целых чисел)

    Нюанс с делением

    Будьте внимательны при делении целых чисел. В C++ деление целого на целое дает целое число (дробная часть отбрасывается).

    Чтобы получить дробный результат, хотя бы одно из чисел должно быть вещественным (double):

    Математическая формула в программировании

    Предположим, нам нужно вычислить площадь круга. В математике формула выглядит так:

    где — площадь круга, — математическая константа (примерно 3.14159), а — радиус круга.

    В коде C++ мы не можем писать верхние индексы, поэтому формула будет записана следующим образом:

    Или, если мы хотим вычислить что-то более сложное, например, дискриминант квадратного уравнения:

    где — дискриминант, — коэффициент при , — коэффициент при , — свободный член.

    В C++ это будет выглядеть так:

    Комментарии

    Хороший код должен быть понятен не только компьютеру, но и человеку. Для этого используются комментарии — текст, который компилятор игнорирует.

  • Однострочный комментарий: начинается с // и действует до конца строки.
  • Многострочный комментарий: начинается с / и заканчивается /.
  • Заключение

    Поздравляю! Вы сделали первый шаг в изучении C++. Сегодня мы узнали: * Из чего состоит минимальная программа. * Как создавать переменные (int, double, string). * Как выводить данные (cout) и считывать их (cin). * Как выполнять базовые математические операции.

    В следующей статье мы разберем условные операторы if и else, чтобы наши программы могли принимать решения и вести себя по-разному в зависимости от ситуации.

    2. Управление потоком выполнения: условные операторы, циклы и создание функций

    Управление потоком выполнения: условные операторы, циклы и создание функций

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

    Однако реальная жизнь полна выбора и повторений. Мы принимаем решения («Если пойдет дождь, я возьму зонт») и выполняем рутинные действия («Пока не помою всю посуду, я не уйду с кухни»). Чтобы программы стали по-настоящему полезными, мы должны научить их ветвиться и зацикливаться.

    В этой статье мы разберем три кита алгоритмического мышления: условные операторы, циклы и функции.

    Условные операторы: искусство выбора

    Условный оператор позволяет программе выполнить определенный блок кода только в том случае, если соблюдается конкретное условие. В C++ основным инструментом для этого является конструкция if (если).

    Базовая конструкция if-else

    Представьте, что вы пишете программу для турникета в метро. Если на карте достаточно денег, турникет открывается. В противном случае — загорается красный свет.

    Разберем синтаксис:

  • if (условие): В круглых скобках пишется логическое выражение. Если оно истинно (true), выполняется код внутри первых фигурных скобок.
  • else: Это необязательный блок «иначе». Он выполняется только тогда, когда условие в if оказалось ложным (false).
  • !Схема работы условного оператора if-else

    Операторы сравнения

    Чтобы формулировать условия, нам нужны операторы сравнения. Они всегда возвращают тип bool (истина или ложь).

    * == — равно (не путайте с = — присваиванием!) * != — не равно * > — больше * < — меньше * >= — больше или равно * <= — меньше или равно

    Логические связки

    Иногда нужно проверить сразу несколько условий. Например, скидка дается, если клиенту больше 60 лет ИЛИ если у него есть купон.

    * && (Логическое И): Истинно, только если оба условия верны. * || (Логическое ИЛИ): Истинно, если хотя бы одно условие верно. * ! (Логическое НЕ): Инвертирует значение (превращает ложь в истину и наоборот).

    Пример сложного условия:

    Каскад условий: else if

    Если вариантов больше двух, используется else if.

    Циклы: сила повторения

    Компьютеры превосходно справляются с монотонной работой. Если вам нужно вывести фразу «Я не буду болтать на уроке» 100 раз, глупо писать 100 строк cout. Для этого существуют циклы.

    Цикл while (Пока)

    Это самый простой цикл. Он выполняется до тех пор, пока условие истинно.

    Осторожно: Если вы забудете изменить переменную counter внутри цикла, условие всегда будет истинным, и программа зависнет в «бесконечном цикле».

    Цикл for (Для)

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

    Синтаксис выглядит так: for (инициализация; условие; обновление) { ... }

    Разберем по шагам:

  • int i = 0: Создается переменная-счетчик (выполняется один раз в начале).
  • i < 5: Проверяется условие. Если истинно — выполняем тело цикла.
  • Тело цикла: Выводится текст.
  • i++: Счетчик увеличивается на 1 (оператор инкремента).
  • Возврат к шагу 2.
  • !Жизненный цикл итерации в for

    Математический пример: Сумма чисел

    Допустим, нам нужно посчитать сумму всех чисел от 1 до . В математике это записывается как сумма арифметической прогрессии:

    Где — искомая сумма, — последнее число последовательности, — переменная итерации, — знак суммирования.

    Реализуем это через цикл:

    Кстати, великий математик Гаусс придумал формулу для быстрого вычисления этой суммы без циклов:

    Где — сумма чисел от 1 до , — количество слагаемых (последнее число). Эта формула работает мгновенно для любого , тогда как циклу потребуется время на перебор.

    Функции: разделяй и властвуй

    По мере роста программы код в main становится огромным и запутанным. Чтобы навести порядок, программисты разбивают код на небольшие логические блоки — функции.

    Функция — это мини-программа внутри вашей программы. Она получает данные на вход, делает работу и (обычно) возвращает результат.

    Анатомия функции

  • Тип возвращаемого значения (int): Тип данных, который функция «выплюнет» в конце. Если функция ничего не возвращает, пишется void.
  • Имя (add): Название, по которому мы будем вызывать функцию.
  • Параметры (int a, int b): Переменные, которые функция принимает извне.
  • return: Команда, которая завершает функцию и передает результат обратно.
  • Как использовать функцию

    Функции обычно объявляют до функции main, чтобы компилятор знал о их существовании.

    Зачем нужны функции?

  • Повторное использование: Написали один раз — используете везде. Не нужно копировать код.
  • Читаемость: calculateTax(salary) понятнее, чем 20 строк математических формул прямо в main.
  • Упрощение отладки: Если ошибка в вычислениях, вы исправляете её только в одном месте — внутри функции.
  • Область видимости переменных

    Важный нюанс: переменные, созданные внутри функции (включая main), не видны в других функциях. Это называется локальной областью видимости.

    Представьте, что каждая функция — это отдельная комната с закрытой дверью. То, что происходит в комнате test, остается в test.

    Заключение

    Сегодня мы превратили C++ из простого калькулятора в мощный инструмент логики. Мы узнали: * Как заставить программу принимать решения с помощью if и else. * Как повторять действия с помощью циклов while и for. * Как структурировать код, создавая собственные функции.

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

    3. Работа с памятью: указатели, ссылки, массивы и динамическое выделение ресурсов

    Работа с памятью: указатели, ссылки, массивы и динамическое выделение ресурсов

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

    Сегодня мы заглянем «под капот» C++. Мы разберемся, как компьютер на самом деле хранит данные, что такое адреса памяти и почему указатели считаются самой сложной, но и самой мощной темой в C++. Если вы поймете эту статью, вы поймете саму суть языка C++.

    Как устроена память компьютера

    Представьте оперативную память (RAM) вашего компьютера как огромный шкаф с миллионами крошечных почтовых ящиков. Каждый ящик имеет свой уникальный номер — адрес.

    Когда вы пишете int a = 10;, происходит следующее:

  • Компьютер находит свободный ящик (или несколько соседних ящиков, так как int занимает 4 байта).
  • Запоминает, что имя a теперь связано с адресом этого ящика.
  • Кладет в этот ящик число 10.
  • !Визуализация ячеек памяти с адресами и значениями

    Массивы: хранение данных рядами

    Часто нам нужно хранить не одно число, а целый список: оценки учеников, координаты точек или температуры за месяц. Создавать для этого 30 переменных (t1, t2, t3...) неудобно. На помощь приходят массивы.

    Массив — это набор переменных одного типа, расположенных в памяти строго друг за другом.

    Объявление и использование

    Важные правила:

  • Нумерация с нуля: Первый элемент имеет индекс 0, второй — 1, последний — N-1. Если массив размером 5, то элемента с индексом 5 не существует (максимальный индекс — 4).
  • Фиксированный размер: При создании обычного массива вы обязаны сказать компьютеру, сколько места зарезервировать. Изменить этот размер позже нельзя.
  • Арифметика адресов в массиве

    Поскольку элементы массива лежат в памяти вплотную друг к другу, компьютер может мгновенно найти любой элемент, зная только адрес начала массива. Формула вычисления адреса выглядит так:

    Где: * — адрес искомого элемента с индексом . * — базовый адрес (адрес самого первого элемента массива, индекс 0). * — индекс элемента, к которому мы хотим обратиться. * — размер одного элемента в байтах (например, для int это обычно 4 байта).

    Именно благодаря этой формуле доступ к array[1000] происходит так же быстро, как и к array[0].

    Указатели: карта мародеров

    Теперь мы подходим к теме, которой пугают новичков. Но на самом деле концепция проста.

    Указатель (Pointer) — это переменная, которая хранит не само значение (как число 10), а адрес другой переменной в памяти.

    Если переменная — это дом, то указатель — это листок бумаги, на котором записан адрес этого дома.

    Операторы работы с адресами

    В C++ есть два главных символа для работы с памятью:

  • & (Амперсанд) — Взятие адреса. «Скажи мне, где ты живешь?»
  • * (Звездочка) — Разыменование. «Пойди по этому адресу и возьми то, что там лежит».
  • Зачем это нужно?

    Указатели позволяют: * Передавать большие объемы данных в функции без копирования (передать адрес дешевле, чем копировать мегабайт данных). * Изменять переменные внутри других функций. * Работать с динамической памятью (об этом ниже).

    !Метафора указателя как записи адреса, ведущего к значению

    Ссылки: безопасные псевдонимы

    Работа с указателями требует внимания: можно случайно обратиться к несуществующей памяти и «уронить» программу. C++ предлагает более безопасную альтернативу — ссылки.

    Ссылка (Reference) — это альтернативное имя (псевдоним) для уже существующей переменной.

    Отличия ссылки от указателя: * Ссылку обязательно нужно инициализировать при создании (нельзя создать ссылку «в никуда»). * Ссылку нельзя переназначить на другую переменную. * У ссылки нет своего адреса в памяти, она сама является адресом, но синтаксис работы с ней выглядит как с обычной переменной (без звездочек).

    Динамическое выделение памяти

    До сих пор мы создавали переменные, размер которых знали заранее. Это называется статическая память (или память на стеке). Но что, если мы пишем программу, которая должна обработать список студентов, и мы не знаем, сколько их будет — 5 или 5000?

    Если мы создадим массив int students[5000], а придет всего 5 человек, мы зря потратим память. Если придет 5001, программа сломается.

    Здесь на сцену выходит динамическая память (куча или Heap).

    Операторы new и delete

    Мы можем попросить у операционной системы выделить нам память прямо во время работы программы.

  • new — выделяет память и возвращает указатель на нее.
  • delete — освобождает память, возвращая ее системе.
  • Утечки памяти

    В C++ нет встроенного уборщика мусора (как в Python или Java). Если вы выделили память через new, но забыли вызвать delete, эта память останется занятой до конца работы программы. Это называется утечкой памяти (Memory Leak). Если программа работает долго (например, сервер), утечки могут съесть всю доступную память компьютера и зависнуть его.

    > «С большой силой приходит большая ответственность». > — Принцип Человека-паука, применимый к C++.

    Стек и Куча (Stack vs Heap)

    Чтобы закрепить материал, давайте разделим память на две основные области:

    | Характеристика | Стек (Stack) | Куча (Heap) | | :--- | :--- | :--- | | Управление | Автоматическое (компилятор) | Ручное (программист) | | Скорость | Очень быстро | Медленнее | | Размер | Ограничен (обычно пара мегабайт) | Ограничен только физической памятью ПК | | Жизнь переменных | Живут, пока выполняется функция | Живут, пока не вызовешь delete | | Пример | int a = 5; | int* p = new int; |

    Заключение

    Сегодня мы прошли одну из самых сложных тем в C++. Мы узнали: * Как массивы хранят данные в непрерывных блоках памяти. * Как использовать формулу для понимания работы массивов. * Что указатели хранят адреса, а ссылки работают как псевдонимы. * Как управлять динамической памятью с помощью new и delete.

    Эти знания открывают вам дорогу к сложным структурам данных и объектно-ориентированному программированию, о котором мы поговорим в следующих статьях курса.

    4. Объектно-ориентированное программирование: классы, инкапсуляция, наследование и полиморфизм

    Объектно-ориентированное программирование: классы, инкапсуляция, наследование и полиморфизм

    В предыдущих статьях мы прошли долгий путь: от написания первой строчки кода до ручного управления памятью через указатели. До сих пор мы писали программы в процедурном стиле. Это когда программа выглядит как набор функций (процедур), которые вызывают друг друга и меняют данные.

    Но когда программы становятся большими — например, вы пишете игру или банковскую систему — процедурный подход начинает давать сбои. Код превращается в «спагетти», где все зависит от всего. Чтобы навести порядок в хаосе, программисты придумали Объектно-Ориентированное Программирование (ООП).

    Сегодня мы изменим ваше мышление. Мы перестанем думать о программе как о наборе инструкций и начнем думать о ней как о наборе взаимодействующих объектов.

    Что такое класс и объект?

    В основе ООП лежат два понятия: класс и объект.

    Представьте, что вы инженер на заводе по производству автомобилей. У вас есть чертеж. На чертеже нарисован автомобиль, указано, где у него колеса, какой двигатель и какого он цвета. Но на этом чертеже нельзя уехать. Это просто схема.

    * Класс — это чертеж (шаблон, описание). Он описывает, какими свойствами и поведением будет обладать сущность. * Объект — это конкретный автомобиль, сошедший с конвейера по этому чертежу. Вы можете создать тысячи автомобилей (объектов) по одному чертежу (классу).

    !Визуализация различия между классом-чертежом и реальными объектами, созданными по нему

    Создание первого класса

    Давайте создадим класс для персонажа компьютерной игры. В C++ классы создаются с помощью ключевого слова class.

    В этом примере:

  • name и health — это поля (переменные внутри класса). Они описывают состояние объекта.
  • sayHello — это метод (функция внутри класса). Он описывает поведение объекта.
  • public: — это спецификатор доступа, о котором мы поговорим прямо сейчас.
  • Инкапсуляция: защита данных

    Представьте, что у вашего персонажа есть здоровье. Если поле health доступно всем (public), то любой кусок кода может случайно написать hero.health = -1000;, и игра сломается.

    Инкапсуляция — это механизм, который объединяет данные и методы работы с ними в одну упаковку (класс) и защищает их от внешнего вмешательства.

    В C++ есть три уровня доступа: * public (публичный): доступно всем из любой части программы. * private (приватный): доступно только методам самого класса. Из main сюда не залезть. * protected (защищенный): доступно классу и его наследникам (об этом ниже).

    Правильный подход — скрыть данные (private) и дать методы для безопасного управления ими (public).

    Теперь мы не можем просто так изменить здоровье. Мы обязаны использовать метод takeDamage, который содержит проверку на ошибки. Это делает код надежным.

    Математика в методах

    Часто методы классов содержат формулы для расчета состояния. Например, расчет урона с учетом брони может выглядеть так:

    где — итоговый полученный урон, — базовый урон атаки, а — показатель брони (в процентах поглощения). Если броня 30%, то множитель будет 0.7.

    Наследование: не повторяй себя

    Допустим, в нашей игре есть не только люди, но и орки, и эльфы. У всех у них есть имя и здоровье. Писать для каждого отдельный класс с одинаковыми полями — это нарушение принципа DRY (Don't Repeat Yourself — не повторяйся).

    Наследование позволяет создать новый класс на основе существующего.

    * Базовый класс (Родитель): содержит общие черты. * Производный класс (Потомок): перенимает черты родителя и добавляет свои.

    Теперь объект класса Orc умеет и move() (от родителя), и roar() (свое). Это экономит сотни строк кода.

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

    Полиморфизм: один интерфейс, разное поведение

    Это самое сложное слово, но самая мощная концепция. Полиморфизм (от греч. «много форм») позволяет обращаться с объектами разных классов одинаково, но получать разный результат.

    Представьте, что вы командир. У вас в отряде есть лучник, мечник и маг. Вы даете команду «Атаковать!». Вам все равно, как они это сделают. Лучник выстрелит, мечник ударит, маг кинет фаербол. Команда одна — действия разные.

    В C++ для этого используются виртуальные функции (virtual).

    Магия указателей и полиморфизма

    Помните указатели из прошлой статьи? Полиморфизм работает именно через них. Мы можем создать указатель на базовый класс Warrior, но положить в него адрес Swordsman.

    Если бы мы не написали virtual в базовом классе, программа вызвала бы метод Warrior::attack («Воин бьет кулаком») для обоих случаев, игнорируя их реальную сущность.

    Заключение

    ООП — это фундамент современной разработки.

  • Классы и объекты позволяют моделировать реальный мир.
  • Инкапсуляция защищает данные от ошибок программиста.
  • Наследование избавляет от дублирования кода.
  • Полиморфизм делает систему гибкой и расширяемой.
  • В следующей статье мы познакомимся со Стандартной библиотекой шаблонов (STL). Вы узнаете, что массивы в C++ могут быть умными, резиновыми и умеют сортировать сами себя. Готовьтесь забыть о ручном управлении памятью, которое мы изучали ранее, ведь STL сделает это за вас!

    5. Продвинутые возможности: шаблоны, обработка исключений и контейнеры STL

    Продвинутые возможности: шаблоны, обработка исключений и контейнеры STL

    Поздравляю! Вы добрались до финальной части нашего курса «Основы программирования на языке C++». Мы уже прошли огромный путь: от «Hello, World!» до создания собственных классов и иерархий наследования. Вы уже умеете моделировать реальный мир с помощью ООП и управлять памятью.

    Однако, если вы посмотрите на свой код критически, вы можете заметить две проблемы:

  • Вам часто приходится писать похожие функции для разных типов данных (например, поиск максимума для int, double и float).
  • Обработка ошибок с помощью if и кодов возврата делает код громоздким и трудночитаемым.
  • Вы тратите много времени на написание велосипедов: динамических массивов, списков и сортировок.
  • Сегодня мы решим все эти проблемы разом. Мы изучим шаблоны, научимся грамотно обрабатывать исключения и познакомимся со Стандартной библиотекой шаблонов (STL) — швейцарским ножом любого C++ программиста.

    Шаблоны (Templates): универсальный код

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

    Без шаблонов вам пришлось бы писать перегрузки:

    Код внутри абсолютно одинаковый! Если вы захотите изменить логику, придется править её в двух местах. Шаблоны позволяют сказать компилятору: «Я напишу алгоритм один раз, а ты сам сгенерируй нужные функции для любых типов».

    Синтаксис шаблона

    Мы используем ключевое слово template, за которым следует описание обобщенного типа (обычно его называют T).

    Когда вы вызываете getMax(5, 10), компилятор видит, что аргументы — целые числа. Он подставляет int вместо T и генерирует код. Это происходит на этапе компиляции, поэтому шаблоны не замедляют работу программы.

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

    Шаблоны можно применять не только к функциям, но и к классам. Именно на этом построена библиотека STL, о которой мы поговорим чуть позже.

    Обработка исключений: когда что-то пошло не так

    В идеальном мире файлы всегда открываются, память всегда выделяется, а пользователи никогда не делят на ноль. В реальности ошибки случаются постоянно.

    Раньше программисты использовали коды ошибок:

    Проблема в том, что эти if можно забыть написать, и программа продолжит работать с некорректными данными, что приведет к катастрофе.

    C++ предлагает механизм исключений (exceptions). Это способ прервать нормальное выполнение программы при возникновении ошибки и передать управление в специальный блок обработки.

    Триада try-catch-throw

  • throw (бросить): Сообщает об ошибке.
  • try (пытаться): Блок кода, в котором мы ожидаем подвох.
  • catch (поймать): Блок, который перехватывает ошибку и решает, что делать.
  • Пример с делением на ноль:

    Если b равно 0, функция divide прекращает работу и «выбрасывает» ошибку. Программа ищет ближайший блок catch. Если она его не найдет, программа аварийно завершится (крашнется).

    Контейнеры STL: прощай, ручное управление памятью

    Помните, как мы мучились с new, delete и массивами фиксированного размера? Забудьте. Standard Template Library (STL) — это набор готовых классов-контейнеров и алгоритмов, написанных профессионалами.

    std::vector — умный массив

    std::vector — это динамический массив, который умеет сам менять свой размер. Вам не нужно знать заранее, сколько в нем будет элементов.

    Главное преимущество вектора — автоматическое управление памятью. Когда вектор уничтожается, он сам вызывает delete для своих данных.

    std::map — словарь

    Иногда нужно хранить пары «Ключ — Значение». Например, телефонную книгу (Имя -> Номер). В STL для этого есть std::map.

    Алгоритмы STL

    STL — это не только контейнеры, но и алгоритмы. Например, сортировка. Вам больше не нужно писать пузырьковую сортировку вручную. Функция std::sort работает максимально эффективно.

    Эффективность алгоритмов сортировки часто оценивается математически. Сложность быстрой сортировки, которую использует STL, описывается формулой:

    Где — примерное количество операций, необходимых для сортировки, — некоторая константа, зависящая от компьютера, — количество элементов в массиве, а — двоичный логарифм от количества элементов.

    Это намного быстрее, чем простые методы сортировки, где количество операций пропорционально . Например, для 1000 элементов даст 1 000 000 операций, а — всего около 10 000.

    !Графическое сравнение эффективности алгоритмов сортировки.

    Пример использования сортировки:

    Итоги курса

    Мы завершаем наш курс «Основы программирования на языке C++». В этой статье мы разобрали инструменты профессионалов:

    * Шаблоны позволяют писать код один раз для всех типов данных. * Исключения помогают контролировать ошибки и не дают программе падать молча. * STL предоставляет готовые, оптимизированные и безопасные контейнеры (vector, map) и алгоритмы (sort).

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

    Удачи в мире C++!