LEARN X · ЗА 20 МИН

C++

Экспресс-тур по C++ за 20 минут: типы, циклы, строки, векторы, STL, классы, шаблоны, указатели и умные указатели — весь язык на одной странице.

C++ — компилируемый язык с ручным управлением памятью, классами, шаблонами и богатой стандартной библиотекой (STL). За 20 минут пробежимся по всему языку: от вывода в консоль до умных указателей. Весь материал — в комментариях к коду, читайте сверху вниз. Примеры рассчитаны на стандарт C++17.

Структура программы и вывод

Любая программа на C++ начинается с функции main.

#include <iostream>   // подключаем библиотеку ввода-вывода

// Однострочный комментарий
/* Многострочный
   комментарий */

int main() {                 // точка входа, возвращает код завершения
    std::cout << "Привет, мир!" << std::endl;  // вывод + перевод строки
    std::cout << "Без endl\n";                 // \n тоже перевод строки
    return 0;                // 0 = успешное завершение
}
// Вывод:
// Привет, мир!
// Без endl

Переменные и типы

int     n   = 42;        // целое
double  pi  = 3.14;      // вещественное (double точнее float)
float   f   = 1.5f;      // одинарная точность
char    c   = 'A';       // один символ (в одинарных кавычках)
bool    flag = true;     // логический: true / false
auto    x   = 10;        // тип выведет компилятор -> int
auto    y   = 2.5;       // -> double
const int MAX = 100;     // константа, менять нельзя

unsigned int u = 7;      // только неотрицательные
long long big = 9000000000LL;  // большое целое

std::cout << n << " " << pi << " " << c << "\n";  // 42 3.14 A
std::cout << sizeof(int) << "\n";  // размер типа в байтах, обычно 4

Ввод-вывод

std::cin читает данные, std::getline — целую строку.

#include <iostream>
#include <string>

int main() {
    int age;
    std::cout << "Возраст: ";
    std::cin >> age;             // читаем число до пробела/перевода строки

    std::cin.ignore();           // убираем '\n' из буфера после >>

    std::string name;
    std::cout << "Имя: ";
    std::getline(std::cin, name); // читаем всю строку, включая пробелы

    std::cout << name << ", " << age << " лет\n";
    return 0;
}

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

int a = 5, b = 3;

// Арифметика: + - * / %  (целочисленное деление отбрасывает дробь)
std::cout << a / b << " " << a % b << "\n";  // 1 2

// Сравнение: ==  !=  <  >  <=  >=
// Логика:    &&  ||  !

if (a > b) {
    std::cout << "a больше\n";
} else if (a == b) {
    std::cout << "равны\n";
} else {
    std::cout << "b больше\n";
}

// Тернарный оператор
int max = (a > b) ? a : b;        // max = 5

// switch — выбор по значению
int day = 3;
switch (day) {
    case 1: std::cout << "Пн\n"; break;  // break обязателен
    case 3: std::cout << "Ср\n"; break;
    default: std::cout << "?\n";
}

Циклы

// for: инициализация; условие; шаг
for (int i = 0; i < 3; i++) {
    std::cout << i << " ";   // 0 1 2
}
std::cout << "\n";

// range-based for: перебор элементов коллекции
int nums[] = {10, 20, 30};
for (int x : nums) {
    std::cout << x << " ";   // 10 20 30
}
std::cout << "\n";

// while: пока условие истинно
int k = 0;
while (k < 3) { std::cout << k; k++; }  // 012
std::cout << "\n";

// do-while: тело выполнится хотя бы раз
int m = 5;
do { std::cout << m; m++; } while (m < 3);  // 5

// break прерывает цикл, continue пропускает итерацию

Строки

std::string — удобная строка из заголовка <string>.

#include <string>

std::string s = "Привет";
s += ", мир";                    // конкатенация
std::cout << s.length() << "\n"; // длина в байтах (UTF-8!)
std::cout << s.size() << "\n";   // то же самое

std::string a = "abc";
std::cout << a[0] << "\n";        // 'a' — доступ по индексу
std::cout << a.substr(1, 2) << "\n";        // "bc" (с позиции 1, длина 2)
std::cout << a.find("b") << "\n";           // 1 (индекс) или string::npos
std::cout << (a == "abc") << "\n";          // 1 (сравнение строк работает)
a.append("!");                              // a = "abc!"
std::cout << a.empty() << "\n";             // 0 (не пустая)

// Число <-> строка
int n = std::stoi("123");        // строка -> int
std::string t = std::to_string(45);  // int -> строка

Массивы и векторы

std::vector — динамический массив, который растёт сам.

#include <vector>

int arr[3] = {1, 2, 3};          // статический массив фиксированной длины
std::cout << arr[0] << "\n";     // 1

std::vector<int> v = {10, 20};   // вектор
v.push_back(30);                 // добавить в конец -> {10,20,30}
v.pop_back();                    // удалить последний -> {10,20}
std::cout << v.size() << "\n";   // 2
std::cout << v[0] << "\n";       // 10
std::cout << v.front() << " " << v.back() << "\n";  // 10 20
v.insert(v.begin(), 5);          // вставить в начало -> {5,10,20}
v.clear();                       // очистить
std::cout << v.empty() << "\n";  // 1

std::vector<int> w(5, 0);        // 5 элементов, все = 0

for (int x : w) std::cout << x;  // 00000

Контейнеры STL

map — ключ-значение, set — уникальные значения, pair — пара.

#include <map>
#include <set>
#include <utility>

std::map<std::string, int> ages;   // словарь (ключи отсортированы)
ages["Аня"] = 25;
ages["Боб"] = 30;
std::cout << ages["Аня"] << "\n";  // 25
std::cout << ages.count("Боб") << "\n";  // 1 (есть ли ключ)
for (auto& [name, age] : ages)     // перебор пар (C++17)
    std::cout << name << "=" << age << " ";  // Аня=25 Боб=30
std::cout << "\n";

std::set<int> uniq = {3, 1, 2, 2};  // дубликаты отбрасываются
uniq.insert(5);                     // {1,2,3,5}
std::cout << uniq.count(2) << "\n"; // 1

std::pair<int, std::string> p = {1, "раз"};
std::cout << p.first << " " << p.second << "\n";  // 1 раз

Функции

// Объявление: тип_возврата имя(параметры)
int square(int x) {
    return x * x;
}

// Параметр по умолчанию
int power(int base, int exp = 2) {
    int r = 1;
    for (int i = 0; i < exp; i++) r *= base;
    return r;
}

// Передача по ссылке (&) — функция меняет оригинал
void increment(int& n) {
    n++;
}

// Перегрузка: одно имя, разные параметры
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }

int main() {
    std::cout << square(5) << "\n";    // 25
    std::cout << power(3) << "\n";     // 9  (exp по умолчанию = 2)
    std::cout << power(2, 3) << "\n";  // 8
    int v = 10;
    increment(v);
    std::cout << v << "\n";            // 11
    std::cout << add(1, 2) << " " << add(1.5, 2.5) << "\n"; // 3 4
}

Указатели и ссылки

Указатель хранит адрес, ссылка — псевдоним переменной.

int x = 42;
int* ptr = &x;            // & — адрес переменной
std::cout << *ptr << "\n"; // * — разыменование -> 42
*ptr = 100;               // меняем x через указатель
std::cout << x << "\n";    // 100

int& ref = x;             // ссылка = другое имя для x
ref = 7;                  // меняет x
std::cout << x << "\n";    // 7

int* empty = nullptr;     // пустой указатель (не 0/NULL)
if (empty == nullptr) std::cout << "пусто\n";

// Динамическая память: new выделяет, delete освобождает
int* num = new int(5);    // выделяем int со значением 5
std::cout << *num << "\n"; // 5
delete num;               // обязательно освободить!

int* arr = new int[3]{1,2,3};  // массив в куче
delete[] arr;             // для массива — delete[]

Классы и ООП

class объединяет данные и методы. Наследование и виртуальные методы дают полиморфизм.

#include <string>

class Animal {
protected:                       // доступно наследникам
    std::string name;
public:
    Animal(std::string n) : name(n) {  // конструктор
        std::cout << "Создан " << name << "\n";
    }
    virtual ~Animal() {}         // виртуальный деструктор

    virtual void sound() {       // virtual — можно переопределить
        std::cout << "...\n";
    }
    std::string getName() { return name; }
};

class Dog : public Animal {      // Dog наследует Animal
public:
    Dog(std::string n) : Animal(n) {}
    void sound() override {      // override — переопределяем
        std::cout << name << ": Гав!\n";
    }
};

int main() {
    Animal* a = new Dog("Рекс"); // Создан Рекс
    a->sound();                  // Рекс: Гав! (полиморфизм)
    delete a;
}

Шаблоны

Шаблоны позволяют писать код, работающий с любым типом T.

// Шаблон функции
template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

// Шаблон класса
template <typename T>
class Box {
    T value;
public:
    Box(T v) : value(v) {}
    T get() { return value; }
};

int main() {
    std::cout << maximum(3, 7) << "\n";       // 7   (T = int)
    std::cout << maximum(2.5, 1.1) << "\n";   // 2.5 (T = double)
    std::cout << maximum('a', 'z') << "\n";   // z

    Box<int> bi(42);
    Box<std::string> bs("hi");
    std::cout << bi.get() << " " << bs.get() << "\n";  // 42 hi
}

Алгоритмы STL

Заголовок <algorithm> + лямбды дают мощные операции над коллекциями.

#include <vector>
#include <algorithm>

std::vector<int> v = {5, 2, 8, 1, 9};

std::sort(v.begin(), v.end());            // {1,2,5,8,9}
std::sort(v.begin(), v.end(),
          [](int a, int b){ return a > b; });  // по убыванию: {9,8,5,2,1}

// Лямбда: [захват](параметры){ тело }
auto it = std::find(v.begin(), v.end(), 8);
if (it != v.end()) std::cout << "найдено\n";

int cnt = std::count_if(v.begin(), v.end(),
                        [](int x){ return x > 4; });  // 3 элемента > 4
std::cout << cnt << "\n";                  // 3

int sum = std::accumulate(v.begin(), v.end(), 0); // нужен <numeric>
std::cout << *std::max_element(v.begin(), v.end()) << "\n"; // 9

std::for_each(v.begin(), v.end(), [](int x){ std::cout << x << " "; });

Умные указатели

Умные указатели из <memory> сами освобождают память — delete не нужен.

#include <memory>

// unique_ptr — единственный владелец, нельзя копировать
std::unique_ptr<int> u = std::make_unique<int>(10);
std::cout << *u << "\n";           // 10
// память освободится автоматически в конце области видимости

// shared_ptr — счётчик ссылок, владельцев может быть много
std::shared_ptr<int> s1 = std::make_shared<int>(20);
std::shared_ptr<int> s2 = s1;      // оба владеют одним объектом
std::cout << *s2 << "\n";          // 20
std::cout << s1.use_count() << "\n"; // 2 (число владельцев)
// объект удалится, когда счётчик станет 0

// Зачем: исключают утечки памяти и двойной delete
Поддержать проект