👩💻 ZTG - графический движок для консолей Windows на С++.
Скомпилируйте библиотеку как статическую и включите ее в свой проект, включите файл ZTG.h
https://github.com/zLouis043/ZTG/
Скомпилируйте библиотеку как статическую и включите ее в свой проект, включите файл ZTG.h
#include "ZTG/ZTG.H"
https://github.com/zLouis043/ZTG/
➡️ Модули (Modules) в C++
Модули - это система сборки и организации кода, представленная в C++20.
C++ Learning 👩💻
Модули - это система сборки и организации кода, представленная в C++20.
• Они улучшают компиляцию и организацию кода, предоставляя более четкий и эффективный способ управления зависимостями.
• Модули заменяют использование препроцессорных директив #include, улучшая время компиляции и предотвращая проблемы с зависимостями и макросами.
• Модули значительно сокращают время компиляции по сравнению с традиционными заголовочными файлами, так как они компилируются только один раз.
• Модули предотвращают проблемы, связанные с макросами и конфликтами имен, поскольку они предоставляют четкие границы и изолированные области видимости.
• Модули упрощают управление зависимостями и организацию кода, что делает проекты более поддерживаемыми и масштабируемыми.C++ Learning 👩💻
➡️ Как включить все стандартные библиотеки одной командой
Чтобы разом включить в проект все стандартные библиотеки, используйте
C++ Learning 👩💻
Чтобы разом включить в проект все стандартные библиотеки, используйте
#include <bits/stdc++.h>. Это особенно полезно в условиях дефицита времени на соревнованиях по программированию.• Например, вы можете заменить этот фрагмент (и многие другие):#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <set>
#include <queue>
#include <map>
• Простой строкой:#include <bits/stdc++.h>
C++ Learning 👩💻
➡️ Злой друг программиста: переопределение ключевых слов
C++ Learning 👩💻
• Переопределение ключевых слов — плохая практика программирования, но это возможно через препроцессор. Это может вводить баги, например, #define true false или #define else.#define int float
#define float char
• Такой код будет работать, хотя это может быть полезно в некоторых ситуациях. Например, если мы используем большую библиотеку и не хотим публичного наследования, мы можем временно отключить защиту доступа перед подключением заголовков библиотеки, а затем снова включить её.#define public private
#include "mylibrary.h"
#undef private
• Это позволяет управлять доступом к библиотеке без её изменения, но требует осторожности.C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое "RAII" (Resource Acquisition Is Initialization) и как это помогает в управлении ресурсами в C++?
Ответ ⬇️
"RAII" — это идиома, при которой инициализация объекта захватывает ресурс, а освобождение ресурса происходит автоматически при уничтожении объекта. Это гарантирует корректное освобождение ресурсов, таких как память или файловые дескрипторы, даже при исключениях.
🗣 Пример:
C++ Learning 👩💻
Что такое "RAII" (Resource Acquisition Is Initialization) и как это помогает в управлении ресурсами в C++?
Ответ ⬇️
🗣 Пример:
#include <iostream>
class File {
public:
File(const char* filename) {
file_ = fopen(filename, "w");
if (file_) {
std::cout << "Файл открыт.\n";
}
}
~File() {
if (file_) {
fclose(file_);
std::cout << "Файл закрыт.\n";
}
}
private:
FILE* file_;
};
int main() {
{
File file("example.txt");
// Работа с файлом
} // Файл автоматически закроется при выходе из блока
// Результат выполнения:
// Файл открыт.
// Файл закрыт.
}
C++ Learning 👩💻
❓ Вопрос на собеседовании
Как работает RVO (Return Value Optimization) в C++, и в каких случаях оно не применяется?
Ответ ⬇️
RVO — это оптимизация, при которой компилятор устраняет временные объекты, возвращаемые из функции, что значительно снижает накладные расходы на создание копий. Однако, есть ситуации, когда RVO не применяется, например, при возврате различных объектов в зависимости от условий внутри функции.
🗣 Пример:
C++ Learning 👩💻
Как работает RVO (Return Value Optimization) в C++, и в каких случаях оно не применяется?
Ответ ⬇️
🗣 Пример:
#include <iostream>
struct MyObject {
MyObject() { std::cout << "Создан объект\n"; }
MyObject(const MyObject&) { std::cout << "Скопирован объект\n"; }
MyObject(MyObject&&) { std::cout << "Перемещён объект\n"; }
};
MyObject createObject(bool flag) {
if (flag) {
return MyObject(); // RVO применяется
} else {
MyObject obj;
return obj; // RVO может не применяться
}
}
int main() {
MyObject obj1 = createObject(true);
MyObject obj2 = createObject(false);
}
C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое "SFINAE" (Substitution Failure Is Not An Error) в C++, и как он применяется в шаблонном программировании?
Ответ ⬇️
SFINAE — это принцип C++, при котором ошибка подстановки шаблонных параметров не приводит к ошибке компиляции, а просто игнорирует неудачные варианты. Это используется для создания разных реализаций шаблонных функций в зависимости от типов.
Пример использования ⚙️
C++ Learning 👩💻
Что такое "SFINAE" (Substitution Failure Is Not An Error) в C++, и как он применяется в шаблонном программировании?
Ответ ⬇️
Пример использования ⚙️
#include <iostream>
#include <type_traits>
// Шаблон для типов, поддерживающих операцию сложения
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type
add(T a, T b) {
return a + b;
}
// Шаблон для других типов (например, строк)
template <typename T>
typename std::enable_if<!std::is_arithmetic<T>::value, void>::type
add(T a, T b) {
std::cout << "Сложение недоступно для этого типа.\n";
}
int main() {
std::cout << add(5, 3) << std::endl; // Сложение чисел
add(std::string("Hello"), std::string("World")); // Строки не поддерживают сложение
return 0;
}
SFINAE позволяет выбирать реализацию функции add() в зависимости от типа аргументов: для числовых типов выполняется сложение, а для других типов выводится сообщение.
C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое rvalue-ссылки в C++ и зачем они нужны?
Ответ ⬇️
Rvalue-ссылки (ссылки на временные объекты) позволяют захватывать и модифицировать временные объекты, избегая ненужного копирования данных. Они обозначаются как T&&. Основное применение rvalue-ссылок — это "перемещение" (move semantics), которое помогает оптимизировать работу с ресурсами. Вместо создания копии и переноса данных, можно использовать rvalue-ссылку и «переместить» содержимое, например, из одного контейнера в другой, обнулив исходный объект.
Пример использования ⚙️
C++ Learning 👩💻
Что такое rvalue-ссылки в C++ и зачем они нужны?
Ответ ⬇️
Пример использования ⚙️
#include <iostream>
#include <vector>
class MyClass {
public:
std::vector<int> data;
MyClass(std::vector<int> d) : data(std::move(d)) {} // перемещающий конструктор
MyClass(MyClass&& other) noexcept : data(std::move(other.data)) {
other.data.clear();
}
};
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
MyClass obj1(std::move(numbers)); // перемещение данных из numbers в obj1
MyClass obj2(std::move(obj1)); // перемещение из obj1 в obj2
std::cout << "Размер obj1 после перемещения: " << obj1.data.size() << std::endl; // Размер obj1 после перемещения: 0
}
C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое перемещение (move semantics) в C++11, как оно работает, и зачем нужен конструктор перемещения?
Ответ ⬇️
Перемещение — это оптимизация, которая позволяет передавать ресурсы (например, память или файлы) из одного объекта в другой без копирования, с помощью конструктора перемещения или оператора перемещения. Это достигается использованием std::move, который превращает объект в rvalue-ссылку, указывающую на временный объект. Конструктор перемещения предотвращает дорогостоящие копирования, делая код более производительным.
Пример использования ⚙️
Если вдруг не поняли, можешь почитать подробное объяснение здесь.
C++ Learning 👩💻
Что такое перемещение (move semantics) в C++11, как оно работает, и зачем нужен конструктор перемещения?
Ответ ⬇️
Пример использования ⚙️
#include <iostream>
#include <vector>
#include <utility> // Для std::move
class MyVector {
private:
int* data;
size_t size;
public:
// Конструктор
MyVector(size_t n) : size(n), data(new int[n]) {
std::cout << "Конструктор\n";
}
// Конструктор перемещения
MyVector(MyVector&& other) noexcept : size(other.size), data(other.data) {
other.data = nullptr; // Передаем ресурсы и обнуляем указатель у источника
other.size = 0;
std::cout << "Конструктор перемещения\n";
}
// Деструктор
~MyVector() {
delete[] data;
std::cout << "Деструктор\n";
}
};
int main() {
MyVector vec1(10); // Создаем объект
MyVector vec2 = std::move(vec1); // Используем конструктор перемещения
// vec1 больше не владеет ресурсами
return 0;
}
// Результат выполнения:
// Конструктор
// Конструктор перемещения
// Деструктор (vec1, ресурсы уже перенесены)
// Деструктор (vec2)
Если вдруг не поняли, можешь почитать подробное объяснение здесь.
C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое perfect forwarding в C++, как оно работает и зачем оно нужно?
Ответ ⬇️
Perfect forwarding — это техника передачи аргументов в функции или конструкторы так, чтобы сохранить их исходные квалификаторы (например, lvalue, rvalue). Она достигается с помощью универсальных ссылок (T&&) и функции std::forward. Perfect forwarding используется для передачи аргументов в шаблонных функциях без лишних копирований.
Пример использования ⚙️
C++ Learning 👩💻
Что такое perfect forwarding в C++, как оно работает и зачем оно нужно?
Ответ ⬇️
Пример использования ⚙️
#include <iostream>
#include <utility>
void process(int& x) {
std::cout << "Lvalue: " << x << "\n";
}
void process(int&& x) {
std::cout << "Rvalue: " << x << "\n";
}
template <typename T>
void forwarder(T&& arg) {
process(std::forward<T>(arg));
}
int main() {
int a = 42;
forwarder(a); // Передаем lvalue
forwarder(100); // Передаем rvalue
return 0;
}
C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое шаблонный метод
Ответ ⬇️
std::enable_if — это шаблонный механизм SFINAE (Substitution Failure Is Not An Error), позволяющий включать или отключать функции или классы на этапе компиляции в зависимости от выполнения условий. Это полезно для создания перегрузок шаблонов или ограничения их использования для определённых типов.
Пример использования ⚙️
C++ Learning 👩💻
Что такое шаблонный метод
std::enable_if в C++, как он работает, и в каких случаях его полезно использовать?Ответ ⬇️
Пример использования ⚙️
#include <iostream>
#include <type_traits>
// Шаблон для целых чисел
template <typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
printType(T value) {
std::cout << "Целое число: " << value << "\n";
}
// Шаблон для чисел с плавающей точкой
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, void>::type
printType(T value) {
std::cout << "Число с плавающей точкой: " << value << "\n";
}
int main() {
printType(42); // Целое число: 42
printType(3.14); // Число с плавающей точкой: 3.14
// printType("Test"); // Ошибка компиляции: шаблон не подходит
}
C++ Learning 👩💻
👩💻 Задача по C++: Удаление дубликатов из вектора с сохранением порядка
Напишите функцию, которая принимает
Пример:
Решение задачи на картинке ☝
C++ Learning 👩💻
Напишите функцию, которая принимает
std::vector и возвращает новый std::vector, содержащий только уникальные элементы, сохраняя их порядок появления.Пример:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 2, 3, 4, 3, 5, 1};
auto result = removeDuplicates(numbers);
for (int num : result) {
std::cout << num << " ";
}
// Ожидаемый результат: 1 2 3 4 5
return 0;
}
Решение задачи на картинке ☝
C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое
Ответ ⬇️
Метод emplace добавляет новый элемент в контейнер, создавая его непосредственно на месте, вместо создания временного объекта и его копирования (как в случае с push_back). Это повышает производительность, особенно при добавлении сложных объектов. Метод emplace вызывает конструктор объекта с переданными аргументами прямо в памяти контейнера.
Пример использования ⚙️
C++ Learning 👩💻
Что такое
emplace в C++ и чем оно отличается от push_back при работе с контейнерами STL?Ответ ⬇️
Пример использования ⚙️
#include <iostream>
#include <vector>
#include <string>
class MyClass {
public:
MyClass(const std::string& name, int value) : name(name), value(value) {
std::cout << "Создан объект: " << name << " со значением " << value << "\n";
}
private:
std::string name;
int value;
};
int main() {
std::vector<MyClass> vec;
// Используем push_back
vec.push_back(MyClass("Object1", 10)); // Создаётся временный объект
// Используем emplace
vec.emplace_back("Object2", 20); // Объект создаётся сразу в контейнере
return 0;
}
C++ Learning 👩💻
❓ Вопрос на собеседовании
Что такое умные указатели в C++ (
Ответ ⬇️
Умные указатели в C++ автоматизируют управление памятью и помогают избежать утечек памяти. Они находятся в заголовке <memory>.
std::unique_ptr владеет ресурсом единолично. При уничтожении указателя ресурс освобождается.
std::shared_ptr позволяет нескольким указателям совместно владеть ресурсом. Ресурс освобождается, когда последний shared_ptr уничтожается.
std::weak_ptr предоставляет доступ к ресурсу, но не увеличивает счётчик ссылок. Используется для предотвращения циклических зависимостей.
Пример использования ⚙️
C++ Learning 👩💻
Что такое умные указатели в C++ (
std::unique_ptr, std::shared_ptr, std::weak_ptr), и чем они отличаются друг от друга?Ответ ⬇️
std::unique_ptr владеет ресурсом единолично. При уничтожении указателя ресурс освобождается.
std::shared_ptr позволяет нескольким указателям совместно владеть ресурсом. Ресурс освобождается, когда последний shared_ptr уничтожается.
std::weak_ptr предоставляет доступ к ресурсу, но не увеличивает счётчик ссылок. Используется для предотвращения циклических зависимостей.
Пример использования ⚙️
#include <iostream>
#include <memory>
int main() {
// unique_ptr: единоличное владение
std::unique_ptr<int> uptr = std::make_unique<int>(10);
std::cout << "unique_ptr: " << *uptr << "\n";
// shared_ptr: совместное владение
std::shared_ptr<int> sptr1 = std::make_shared<int>(20);
std::shared_ptr<int> sptr2 = sptr1; // sptr2 теперь также владеет ресурсом
std::cout << "shared_ptr: " << *sptr1 << ", use_count: " << sptr1.use_count() << "\n";
// weak_ptr: не увеличивает счётчик ссылок
std::weak_ptr<int> wptr = sptr1;
if (auto locked = wptr.lock()) {
std::cout << "weak_ptr: " << *locked << "\n";
}
return 0;
}
C++ Learning 👩💻