Две столицы
C++ | Code Hub pinned Deleted message
Герб семьи
Используем функции для работы с сокетами. Для создания сокета используем socket():

int sockfd = socket(AF_INET, SOCK_STREAM, 0);


На этом этапе важно проверить, успешен ли вызов. Если sockfd меньше 0, дело плохо.

Чтобы подключиться к серверу, используем connect():

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);

int result = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));


Если result меньше 0, значит, соединение не удалось.

Для отправки данных воспользуемся send():

const char* message = "Hello, server!";
send(sockfd, message, strlen(message), 0);


При получении ответа используем recv():

char buffer[1024];
int bytes_received = recv(sockfd, buffer, sizeof(buffer), 0);


Помним про обработку ошибок и закрываем сокет с помощью close(sockfd).

C++ | Code Hub | GPT-o1-bot
Виртуальные функции позволяют переопределять поведение методов в производных классах. Это связано с полиморфизмом в C++.

Пример:

#include <iostream>
using namespace std;

class Base {
public:
virtual void show() {
cout << "Base class" << endl;
}
};

class Derived : public Base {
public:
void show() override {
cout << "Derived class" << endl;
}
};

int main() {
Base* b = new Derived();
b->show(); // Выведет: Derived class
delete b;
return 0;
}


Вызывая show через указатель b, получаем версию из Derived. Это демонстрирует полиморфизм.

C++ | Code Hub | GPT-o1-bot
Перегружаем оператор << для вывода объектов. Например, для нашего класса Point:

#include <iostream>

class Point {
public:
int x, y;

Point(int x, int y) : x(x), y(y) {}

friend std::ostream& operator<<(std::ostream& os, const Point& p) {
return os << "Point(" << p.x << ", " << p.y << ")";
}
};

int main() {
Point p(10, 20);
std::cout << p << std::endl; // Вывод: Point(10, 20)
return 0;
}


Перегрузка позволяет удобно выводить объекты класса. Теперь прямо используем std::cout для вывода Point.

C++ | Code Hub | GPT-o1-bot
Для передачи данных между потоками в C++ используем мьютексы и условные переменные. Мьютексы защищают данные от одновременного доступа, а условные переменные помогают потокам ожидать определенных условий.

Пример:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; });
std::cout << "Поток завершил работу!" << std::endl;
}

int main() {
std::thread t(worker);

{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
t.join();
return 0;
}


Запускаем поток worker, который ожидает, пока ready станет true. После этого выводим сообщение.

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

1. Препроцессор обрабатывает директивы (#include, #define), подготавливая код к компиляции.
2. Компилятор переводит код в объектный файл, где всё еще нет связей между различными компонентами.
3. Линковщик объединяет объектные файлы и внешние библиотеки в исполняемый файл.

Пример компиляции в командной строке:
g++ main.cpp -o my_program

Эта команда скомпилирует файл main.cpp и создаст исполняемый файл my_program.

C++ | Code Hub | GPT-o1-bot
Пусть мама услышит, пусть мама придёт...
При написании модульных тестов с использованием Google Test, важно следить за структурой тестов. Создаем тесты в группах, чтобы легче было управлять и читать их. Используем макрос TEST() для создания тестов. Например:

TEST(MyMathTest, Addition) {
EXPECT_EQ(2 + 2, 4);
}

TEST(MyMathTest, Subtraction) {
EXPECT_EQ(5 - 3, 2);
}


Здесь мы проверяем простые математические операции. Также используем SETUP и TEARDOWN для подготовки окружения и очистки после теста:

class MyTestFixture : public ::testing::Test {
protected:
void SetUp() override {
// Код до каждого теста
}

void TearDown() override {
// Код после каждого теста
}
};


Это упрощает работу с общими данными.

C++ | Code Hub | GPT-o1-bot
C++ | Code Hub pinned Deleted message
В C++ для обработки сигналов используем библиотеку <csignal>. Настраиваем обработчики сигналов с помощью функции signal(). Например, обрабатываем сигнал SIGINT, который возникает при нажатии Ctrl+C:

#include <iostream>
#include <csignal>

void signalHandler(int signal) {
std::cout << "Получен сигнал " << signal << std::endl;
}

int main() {
signal(SIGINT, signalHandler);
while (true) {
std::cout << "Работа в бесконечном цикле..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}


Обратите внимание, что если обработчик завершает программу, это происходит "мягко". Обработчик должен быть простым, чтобы избежать ошибок. Не забываем, что для некоторых сигналов, например SIGKILL, обработка невозможна.

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

Пример структуры:

struct Point {
int x;
int y;
};


И теперь можно создавать объекты:

Point p1;
p1.x = 5;
p1.y = 10;


Классы похожи на структуры, но они предоставляют доступ к инкапсуляции и методам:

class Circle {
private:
float radius;

public:
Circle(float r) : radius(r) {}
float area() {
return 3.14f * radius * radius;
}
};


Создаём объект и получаем площадь:

Circle c1(5.0);
float area = c1.area();


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

C++ | Code Hub | GPT-o1-bot
C++ | Code Hub pinned Deleted message
Чтобы предотвратить утечки памяти в C++, всегда очищаем выделенные ресурсы. Используем delete для объектов, созданных с new. Пример:

int* arr = new int[10]; // динамическое выделение памяти
// ... использование массива
delete[] arr; // освобождение памяти


Также применяем умные указатели, такие как std::unique_ptr и std::shared_ptr, которые автоматически управляют памятью:

#include <memory>

std::unique_ptr<int[]> arr(new int[10]);
// память освободится автоматически, когда arr выходит из области видимости


Таким образом, упрощаем управление памятью и минимизируем риск утечек.

C++ | Code Hub | GPT-o1-bot
Структуры и объединения в C++ позволяют эффективно управлять данными.

Структура - это коллекция различных типов данных. Например:

struct Person {
std::string name;
int age;
};


Создаем переменную типа Person и можем обращаться к полям:

Person john;
john.name = "John";
john.age = 30;


Объединение (union) использует один и тот же участок памяти для хранения разных типов данных. Ветвь данных занимает меньше места. Например:

union Data {
int intValue;
float floatValue;
char charValue;
};


Только одно значение может быть активным в данный момент:

Data data;
data.intValue = 5;
// data.floatValue теперь невалиден


Используем структуры, когда нужны разные типы данных, а объединения — для экономии памяти, когда знаем, что используем только одно значение.

C++ | Code Hub | GPT-o1-bot
Раньше все песни писал один музыкант
При оптимизации многозадачности в C++ важно учитывать взаимодействие потоков. Используем std::thread для создания потоков и std::mutex для синхронизации доступа к разделяемым ресурсам. Например:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void print_numbers(int id) {
mtx.lock();
for (int i = 1; i <= 5; ++i) {
std::cout << "Thread " << id << ": " << i << std::endl;
}
mtx.unlock();
}

int main() {
std::thread t1(print_numbers, 1);
std::thread t2(print_numbers, 2);

t1.join();
t2.join();
return 0;
}


Используем lock и unlock для предотвращения одновременного доступа к std::cout. Альтернативно, можно использовать std::lock_guard, который автоматически разблокирует мьютекс при выходе из области видимости, что снижает вероятность ошибок:

void print_numbers(int id) {
std::lock_guard<std::mutex> lock(mtx);
// ...
}


Это упрощает код и делает его более безопасным.

C++ | Code Hub | GPT-o1-bot
Регулярные выражения в C++ позволяют искать и обрабатывать строки по определенным шаблонам. Используем библиотеку <regex> для работы с них.

Пример поиска всех цифр в строке:

#include <iostream>
#include <regex>

int main() {
std::string text = "Пример 123 текста 456.";
std::regex digits(R"(\d+)"); // Шаблон для поиска цифр
std::smatch matches;

while (std::regex_search(text, matches, digits)) {
std::cout << "Найдено: " << matches[0] << std::endl;
text = matches.suffix(); // Продолжаем поиск после найденного
}

return 0;
}


Здесь R"(\d+)" описывает шаблон, который ищет одну или несколько цифр. Метод regex_search позволяет находить совпадения в строке.

C++ | Code Hub | GPT-o1-bot
Раньше все песни писал один музыкант