C++ Learning
10.6K subscribers
1.48K photos
4 videos
7 files
1.03K links
№ 4974310652

Обучающий канал по C++

По всем вопросам @mascarov_valentin

Реклама на бирже - https://telega.in/c/Learning_pluses
Download Telegram
⚙️ std::unordered_map

В C++ std::unordered_map из заголовка <unordered_map> представляет собой хэш-таблицу, которая обеспечивает быстрый доступ к элементам по ключу. В отличие от std::map, элементы хранятся в произвольном порядке, а операции поиска выполняются за O(1) в среднем случае.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос на собеседовании

Что такое pimpl idiom в C++ и когда его использовать?

Ответ ⬇️
Pimpl idiom (Pointer to Implementation) — это паттерн, который скрывает реализацию класса за указателем на скрытый тип в заголовочном файле. Это улучшает инкапсуляцию, минимизирует зависимости и ускоряет компиляцию.

Пример использования ⚙️
// MyClass.h
#include <memory>

class MyClassImpl; // Forward declaration

class MyClass {
public:
MyClass();
void someFunction();

private:
std::unique_ptr<MyClassImpl> pImpl; // Указатель на скрытую реализацию
};

// MyClass.cpp
#include "MyClass.h"
#include <iostream>

class MyClassImpl {
public:
void someFunctionImpl() { std::cout << "Hello, World!\n"; }
};

MyClass::MyClass() : pImpl(std::make_unique<MyClassImpl>()) {}
void MyClass::someFunction() { pImpl->someFunctionImpl(); }

// main.cpp
#include "MyClass.h"

int main() {
MyClass obj;
obj.someFunction();
return 0;
}

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


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::any_cast()

Метод std::any_cast() используется для извлечения значения из объекта типа std::any. Этот тип может содержать значение любого типа, и std::any_cast позволяет безопасно получить его, если тип извлекаемого значения совпадает с типом, указанным в аргументе.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::filesystem::create_directory

Метод std::filesystem::create_directory из заголовка <filesystem> используется для создания новой директории. Это полезно для программ, которые работают с файловыми структурами и должны создавать папки динамически.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
Что будет выведено при выполнении кода?

Пояснение
⬇️
Функции print перегружены для разных типов аргументов: int, double, и const char*. Компилятор выбирает подходящую версию функции в зависимости от переданного типа. Код корректно компилируется и выполняется, выводя Integer: 10, Double: 3.14, и String: Hello.


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
➡️ auto & decltype

auto-типизированные переменные выводятся компилятором на основе типа их инициализатора.
Чрезвычайно полезно с точки зрения удобочитаемости, особенно для сложных типов:

// std::vector<int>::const_iterator cit = v.cbegin();
auto cit = v.cbegin(); // альтернатива

// std::shared_ptr<vector<uint32_t>> demo_ptr(new vector<uint32_t>(0);
auto demo_ptr = make_shared<vector<uint32_t>>(0); // альтернатива


Функции также могут выводить тип возвращаемого значения с помощью auto. В C++11 тип возвращаемого значения должен быть указан либо явно, либо с помощью decltype, например:

template <typename X, typename Y>
auto add(X x, Y y) -> decltype(x + y)
{
return x + y;
}
add(1, 2); // == 3
add(1, 2.0); // == 3.0
add(1.5, 1.5); // == 3.0


Приведенная выше форма определения возвращаемого типа называется trailing return type, т.е. -> return-type.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Как это работает? — Передача аргументов в C++

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

➡️ Как это работает:

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

Развернутый аналог:
void modifyValue(const int &value) {
// value нельзя изменить
}


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::ofstream

std::ofstream из заголовка <fstream> используется для записи данных в файл. Это удобный инструмент для работы с файлами, позволяющий записывать текстовую или бинарную информацию.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::byte

std::byte из заголовка <cstddef> предоставляет тип для работы с данными на уровне байтов. Это полезно для низкоуровневой работы с памятью и сетевыми протоколами.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос на собеседовании

Как работает std::atomic в C++, и в чём его преимущество перед обычными переменными в многопоточном программировании?

Ответ ⬇️
std::atomic — это шаблонный класс из библиотеки <atomic>, который предоставляет атомарные операции с переменными, гарантируя их безопасность в многопоточной среде. Используя атомарные операции, вы избегаете гонок данных без необходимости явно использовать мьютексы.

Пример использования ⚙️
#include <iostream>
#include <atomic>
#include <thread>

std::atomic<int> counter(0);

void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1);
}
}

int main() {
std::thread t1(increment);
std::thread t2(increment);

t1.join();
t2.join();

std::cout << "Итоговый счётчик: " << counter << std::endl; // 2000
return 0;
}


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос на собеседовании

Как работает std::atomic в C++, и в чём его преимущество перед обычными переменными в многопоточном программировании?

Ответ ⬇️
std::atomic — это шаблонный класс из библиотеки <atomic>, который предоставляет атомарные операции с переменными, гарантируя их безопасность в многопоточной среде. Используя атомарные операции, вы избегаете гонок данных без необходимости явно использовать мьютексы.

Пример использования ⚙️
#include <iostream>
#include <atomic>
#include <thread>

std::atomic<int> counter(0);

void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1);
}
}

int main() {
std::thread t1(increment);
std::thread t2(increment);

t1.join();
t2.join();

std::cout << "Итоговый счётчик: " << counter << std::endl; // 2000
return 0;
}


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
🚫 Антипаттерн недели: Использование явных циклов для поиска в контейнерах

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

✔️ Используйте алгоритмы из <algorithm>, такие как std::find, чтобы упростить код и улучшить читаемость.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос на собеседовании

Что такое std::allocator в C++, и как его можно использовать для управления памятью?

Ответ ⬇️
std::allocator — это стандартный шаблонный класс, предоставляющий низкоуровневые инструменты для управления памятью в STL-контейнерах. Он позволяет настраивать аллокацию памяти, предоставляя методы для выделения, освобождения и построения объектов.

Пример использования ⚙️
#include <iostream>
#include <memory>

int main() {
std::allocator<int> allocator;

// Выделяем память для 3 целых чисел
int* arr = allocator.allocate(3);

// Конструируем элементы
allocator.construct(arr, 10);
allocator.construct(arr + 1, 20);
allocator.construct(arr + 2, 30);

// Выводим значения
for (int i = 0; i < 3; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;

// Уничтожаем и освобождаем память
for (int i = 0; i < 3; ++i) {
allocator.destroy(arr + i);
}
allocator.deallocate(arr, 3);

return 0;
}


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::atomic_flag

std::atomic_flag из заголовка <atomic> представляет собой простой атомарный флаг, который можно использовать для реализации низкоуровневой синхронизации.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос на собеседовании

Что такое constexpr в C++ и в чём его отличие от const?

Ответ ⬇️
constexpr — это спецификатор в C++, который указывает, что значение выражения или функции может быть вычислено на этапе компиляции, если это возможно. В отличие от const, который просто запрещает изменение значения, constexpr гарантирует, что вычисления происходят на этапе компиляции (при условии, что все входные данные известны на этом этапе).

constexpr используется для оптимизации кода, особенно в вычислениях, которые можно заранее предсказать.


Пример использования ⚙️
#include <iostream>

constexpr int square(int x) {
return x * x; // Вычисляется на этапе компиляции
}

int main() {
constexpr int result = square(5); // Результат вычислен на этапе компиляции
std::cout << "Результат: " << result << std::endl;

int value = 10;
std::cout << "Результат: " << square(value) << std::endl; // Выполняется во время выполнения
return 0;
}


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::chrono::steady_clock

std::chrono::steady_clock из заголовка <chrono> представляет часы с монотонным ходом, которые никогда не корректируются. Это полезно для измерения времени выполнения или задержек.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::barrier

std::barrier из заголовка <barrier> (доступно с C++20) синхронизирует выполнение потоков, ожидая, пока все участники не достигнут определённой точки (барьера). Это полезно для координации действий в многопоточных приложениях.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::monostate

std::monostate из заголовка <variant> используется как «пустой» тип внутри std::variant. Это полезно для добавления незначимого состояния, которое можно обработать отдельно.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопрос на собеседовании

Что такое Placement new в C++ и как оно используется?

Ответ ⬇️
Placement new — это форма оператора new, которая позволяет разместить объект в заранее выделенной области памяти. Вместо выделения памяти на куче, как это делает обычный new, placement new создаёт объект в памяти, адрес которой передаётся в качестве аргумента.

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


Пример использования ⚙️
#include <iostream>
#include <new> // Для placement new

int main() {
alignas(alignof(int)) char buffer[sizeof(int)]; // Буфер для хранения объекта
int* ptr = new (buffer) int(42); // Размещение объекта в buffer

std::cout << "Значение: " << *ptr << std::endl; // 42
std::cout << "Адрес объекта: " << static_cast<void*>(buffer) << std::endl;
std::cout << "Адрес через указатель: " << ptr << std::endl;

ptr->~int(); // Явно вызываем деструктор, так как память не освобождается автоматически
return 0;
}


C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ std::move_iterator

Итератор std::move_iterator позволяет преобразовать обычный итератор в итератор, который перемещает элементы вместо их копирования. Это особенно полезно при работе с контейнерами, содержащими "тяжелые" объекты, такие как std::string или std::vector, чтобы избежать лишних копирований.

C++ Learning 👩‍💻
Please open Telegram to view this post
VIEW IN TELEGRAM