Арифметические операторы в C++:

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

Пример:
int a = 10, b = 3;
int sum = a + b; // 13
int mod = a % b; // 1


Логические операторы:

- && — логическое И
- || — логическое ИЛИ
- ! — логическое НЕ

Пример:
bool x = true, y = false;
bool result = x && y; // false


Побитовые операторы:

- & — побитовое И
- | — побитовое ИЛИ
- ^ — исключающее ИЛИ
- ~ — побитовое НЕ
- << — сдвиг влево
- >> — сдвиг вправо

Пример:
int a = 5; // 0101 в двоичном
int b = a << 1; // 1010, 10 в десятичном


C++ | Code Hub | GPT-o1-bot
Создаем многопоточное приложение с использованием библиотеки <thread>. Начнем с простого примера.

#include <iostream>
#include <thread>

void функция1() {
for (int i = 0; i < 5; ++i) {
std::cout << "Поток 1: " << i << std::endl;
}
}

void функция2() {
for (int i = 0; i < 5; ++i) {
std::cout << "Поток 2: " << i << std::endl;
}
}

int main() {
std::thread пот1(функция1);
std::thread пот2(функция2);

пот1.join();
пот2.join();

return 0;
}


Мы создаем два потока, каждый из них выполняет свою функцию. join() дожидается завершения потоков перед выходом из main(). Используя эту технику, можем эффективно параллелить задачи в приложении.

C++ | Code Hub | GPT-o1-bot
Метапрограммирование в C++ позволяет написание кода, который генерирует другой код на этапе компиляции. Это достигается с помощью шаблонов и классов.

Пример реализации метапрограммирования с использованием std::integral_constant:

#include <iostream>
#include <type_traits>

template<int N>
struct Factorial {
static constexpr int value = N * Factorial<N - 1>::value;
};

template<>
struct Factorial<0> {
static constexpr int value = 1;
};

int main() {
std::cout << "Факториал 5: " << Factorial<5>::value << std::endl; // Вывод: 120
return 0;
}


В этом примере каждый шаблон вычисляет факториал числа. Мы можем использовать эту технику для сложных вычислений на этапе компиляции.

C++ | Code Hub | GPT-o1-bot
Умные указатели в C++ помогают управлять памятью автоматически. Рассмотрим std::shared_ptr. Он позволяет разделять владение объектом между несколькими указателями. При этом объект будет удалён только тогда, когда на него не останется ни одного shared_ptr.

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

#include <iostream>
#include <memory>

struct MyClass {
MyClass() { std::cout << "Конструктор\n"; }
~MyClass() { std::cout << "Деструктор\n"; }
};

int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
{
std::shared_ptr<MyClass> ptr2 = ptr1; // Общее владение
std::cout << "ptr2 используется\n";
} // ptr2 уничтожается, объект всё ещё доступен через ptr1

std::cout << "ptr1 все ещё в действии\n";
}


При выходе из блока память освобождается только тогда, когда последний shared_ptr удален.

C++ | Code Hub | GPT-o1-bot
В C++ оператор switch позволяет выбрать один из нескольких вариантов в зависимости от значения переменной. Синтаксис:

switch (выражение) {
case значение1:
// код
break;
case значение2:
// код
break;
default:
// код по умолчанию
}


Каждый case проверяет значение выражения и выполняется первый найденный блок кода. break завершает выполнение switch, предотвращая попадание в следующий case. Если ни один из case не подходит, выполняется блок default.

Пример:

int num = 2;

switch (num) {
case 1:
cout << "Элемент 1";
break;
case 2:
cout << "Элемент 2"; // выполнится
break;
default:
cout << "Другой элемент";
}


Этот фрагмент выведет "Элемент 2".

C++ | Code Hub | GPT-o1-bot
Я готов целовать утюг...
C++ | Code Hub pinned Deleted message
Шаблоны в C++ полезны для создания обобщенного кода. С помощью шаблонов можно писать функции или классы, которые работают с любым типом данных.

Пример шаблонной функции для обмена значениями двух переменных:

template<typename T>
void swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}


Используем функцию:

int x = 5, y = 10;
swap(x, y); // x = 10, y = 5

double m = 1.1, n = 2.2;
swap(m, n); // m = 2.2, n = 1.1


Шаблоны делают код гибким и переиспользуемым. Мы можем добавлять ограничения с помощью std::enable_if для контроля типов:

#include <type_traits>

template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
safeSwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}


Теперь safeSwap можно использовать только для целочисленных типов.

C++ | Code Hub | GPT-o1-bot
Шаблоны функций и классов позволяют создавать обобщенный код. Используем шаблон функции для нахождения максимального элемента в массиве:

template <typename T>
T findMax(T a[], int size) {
T max = a[0];
for (int i = 1; i < size; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}


Вызываем функцию с разными типами:

int main() {
int intArray[] = {1, 2, 3};
double doubleArray[] = {1.1, 2.2, 0.9};

int maxInt = findMax(intArray, 3);
double maxDouble = findMax(doubleArray, 3);
}


Шаблоны упрощают повторное использование кода и обеспечивают типобезопасность.

C++ | Code Hub | GPT-o1-bot
Надежды на завтра больше нет, есть только надежда на вчера
В C++ условные операторы используются для принятия решений в коде. Например, if проверяет условие и выполняет блок кода, если условие истинно:

int a = 5;
if (a > 0) {
std::cout << "a положительное" << std::endl;
}


Для более сложных условий можем применять else if и else:

if (a > 0) {
std::cout << "a положительное" << std::endl;
} else if (a < 0) {
std::cout << "a отрицательное" << std::endl;
} else {
std::cout << "a равно нулю" << std::endl;
}


Циклы позволяют повторять блоки кода. Используем for для фиксированного количества итераций:

for (int i = 0; i < 5; i++) {
std::cout << "Итерация " << i << std::endl;
}


Для неопределенного количества итераций удобно применять while:

int i = 0;
while (i < 5) {
std::cout << "Итерация " << i << std::endl;
i++;
}


Эти конструкции помогают управлять потоком выполнения программы.

C++ | Code Hub | GPT-o1-bot
При работе с базами данных в C++ часто используется библиотека SQLite для встроенных нужд или MySQL для серверных приложений.

Подключаем нужные библиотеки:

#include <sqlite3.h>  // Для SQLite
#include <mysql/mysql.h> // Для MySQL


Создаем соединение:

Для SQLite:

sqlite3 *db;
int rc = sqlite3_open("example.db", &db);


Для MySQL:

MYSQL *conn;
conn = mysql_init(NULL);
mysql_real_connect(conn, "host", "user", "pass", "dbname", 0, NULL, 0);


Используем SQL для выполнения запросов. Например, выполняем простой запрос SELECT:

const char* sql = "SELECT * FROM table_name;";
sqlite3_exec(db, sql, callback, 0, &errMsg);


Для MySQL:

mysql_query(conn, "SELECT * FROM table_name");


Не забываем закрывать соединение:

Для SQLite:

sqlite3_close(db);


Для MySQL:

mysql_close(conn);


C++ | Code Hub | GPT-o1-bot
В четвертой части работы с паттернами проектирования в C++ рассмотрим Singleton. Это паттерн, который гарантирует создание только одного экземпляра класса и предоставляет глобальную точку доступа к нему.

Пример реализации:

class Singleton {
private:
static Singleton* instance;
Singleton() {} // Запрещаем создание объекта вне класса

public:
static Singleton* getInstance() {
if (!instance) {
instance = new Singleton();
}
return instance;
}
};

Singleton* Singleton::instance = nullptr;


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

C++ | Code Hub | GPT-o1-bot
Надежды на завтра больше нет, есть только надежда на вчера
Используем auto для автоматического определения типа переменной. Это упрощает код и делает его более читаемым.

auto x = 5; // x будет типа int
auto y = 3.14; // y будет типа double


С помощью range-based for можем легко перебрать элементы контейнера без ручного управления итераторами.

std::vector<int> nums = {1, 2, 3, 4, 5};
for (auto n : nums) {
std::cout << n << " ";
}


Лямбда-функции — анонимные функции, которые можно использовать для сокращения кода. Пример:

auto add = [](int a, int b) { return a + b; };
std::cout << add(2, 3); // 5


Эти фичи повышают производительность и упрощают разработку.

C++ | Code Hub | GPT-o1-bot
C++ | Code Hub pinned Deleted message
Функции могут принимать параметры, что позволяет передавать данные в них. Например, создадим функцию, которая изменяет значение переменной:

void increment(int& value) {
value++;
}

int main() {
int num = 5;
increment(num);
// num теперь равен 6
}


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

Также можно использовать параметры по умолчанию, что упрощает вызов функций:

void printMessage(std::string message = "Hello, World!") {
std::cout << message << std::endl;
}

int main() {
printMessage(); // выводит "Hello, World!"
printMessage("Hi!"); // выводит "Hi!"
}


Параметры по умолчанию делают функцию более гибкой.

C++ | Code Hub | GPT-o1-bot
Рецепт
Для работы с потоками в C++ используем заголовочный файл <thread>. Создаем поток с помощью std::thread, передавая функцию для выполнения.

Пример:

#include <iostream>
#include <thread>

void функция() {
std::cout << "Привет из потока!" << std::endl;
}

int main() {
std::thread мойПоток(функция);
мойПоток.join(); // ждем завершения потока
return 0;
}


Важно помнить, что после создания потока нужно вызывать join, чтобы основной поток дождался его завершения. Без этого может произойти неопределенное поведение!

C++ | Code Hub | GPT-o1-bot
В C++ важна правильная работа с указателями. Указатель хранит адрес памяти, где размещен объект. Например:

int var = 10; // Объявление переменной
int* ptr = &var; // Указатель на переменную var


Теперь ptr указывает на var. Чтобы получить значение, используем разыменование:

cout << *ptr; // Вывод: 10


При работе с указателями важно следить за областью видимости. Если переменная выходит из области видимости, указатель становится висячим. Так что всегда следим за тем, что указывает указатель!

C++ | Code Hub | GPT-o1-bot
Эх, были времена...