C++ собеседования
839 subscribers
106 photos
222 links
Подготовка к собеседованиям на позицию C/C++ разработчик

Еще больше на сайте https://frontview-it.ru

Backend собеседования - @frontview_backend
C/C++ работа - @frontview_cpp_vacancies
Все IT вакансии - @frontview_all_vacancies
Download Telegram
🔥 Объясни принципы работы Qt

Qt — это кроссплатформенный фреймворк для разработки графических интерфейсов и приложений на C++. Основные принципы работы Qt включают сигналы и слоты, событийно-ориентированную архитектуру и поддержку кроссплатформенности.

Сигналы и слоты — это механизм, позволяющий объектам взаимодействовать друг с другом. Сигналы отправляются, когда происходит определенное событие, а слоты — это функции, которые обрабатывают эти события. Это позволяет создавать гибкие и модульные приложения.

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


#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[]) {
QApplication app(argc, argv);

QPushButton button("Click Me");
QObject::connect(&button, &QPushButton::clicked, &app, &QApplication::quit);

button.show();
return app.exec();
}


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

Кроссплатформенность Qt достигается за счет абстракции платформенных деталей, что позволяет разрабатывать приложения, которые работают на различных операционных системах без изменения кода.

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

Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥1
🔥 Что такое std::weak_ptr и когда его использовать?

std::weak_ptr — это умный указатель в C++, который предоставляет неблокирующую ссылку на объект, управляемый std::shared_ptr. В отличие от std::shared_ptr, std::weak_ptr не увеличивает счетчик ссылок на объект, что помогает избежать циклических зависимостей и утечек памяти.

Основное применение std::weak_ptr — это кэширование и предотвращение циклических зависимостей. Например, в графах или деревьях, где узлы могут ссылаться друг на друга, использование std::shared_ptr может привести к утечкам памяти. std::weak_ptr позволяет безопасно проверять, существует ли объект, без его удержания.

Для получения std::shared_ptr из std::weak_ptr используется метод lock(). Если объект уже удален, lock() вернет пустой std::shared_ptr.

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


#include <iostream>
#include <memory>

int main() {
std::shared_ptr<int> sp = std::make_shared<int>(42);
std::weak_ptr<int> wp = sp;

if (auto locked = wp.lock()) {
std::cout << *locked << std::endl; // Вывод: 42
} else {
std::cout << "Object no longer exists" << std::endl;
}

sp.reset(); // Удаляем объект

if (auto locked = wp.lock()) {
std::cout << *locked << std::endl;
} else {
std::cout << "Object no longer exists" << std::endl; // Вывод: Object no longer exists
}

return 0;
}


std::weak_ptr — это важный инструмент для управления памятью в сложных структурах данных.

Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61
🔥 Как управлять памятью в многопоточных приложениях?

Управление памятью в многопоточных приложениях C++ требует особого внимания к синхронизации и безопасности данных. Основные аспекты включают использование умных указателей, синхронизацию доступа и избежание гонок данных.

Умные указатели, такие как std::shared_ptr и std::weak_ptr, помогают управлять временем жизни объектов. Однако std::shared_ptr не является потокобезопасным при одновременной модификации из нескольких потоков. Для этого требуется внешняя синхронизация, например, с помощью мьютексов.

Синхронизация доступа к общим данным осуществляется с помощью мьютексов std::mutex и других примитивов синхронизации, таких как std::lock_guard и std::unique_lock. Они предотвращают одновременный доступ к данным, что может привести к гонкам данных.

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


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

std::mutex mtx;
int sharedData = 0;

void increment() {
std::lock_guard<std::mutex> lock(mtx);
++sharedData;
}

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

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

std::cout << "Shared Data: " << sharedData << std::endl; // 2

return 0;
}


Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91
🔥 Что такое структура и как ее использовать?

Структура — это пользовательский тип данных, который позволяет объединять переменные разных типов под одним именем. Она используется для моделирования объектов реального мира и организации данных.

Объявление структуры начинается с ключевого слова struct, за которым следует имя структуры и список её членов:


#include <iostream>
#include <string>

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

int main() {
Person person;
person.name = "Alice";
person.age = 30;
person.height = 1.75;

std::cout << "Name: " << person.name << std::endl;
std::cout << "Age: " << person.age << std::endl;
std::cout << "Height: " << person.height << "m" << std::endl;

return 0;
}


Структуры могут содержать методы, что делает их похожими на классы. Однако, по умолчанию, все члены структуры имеют public доступ, в отличие от классов, где они private.

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

Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥3🤩1
🔥 Объясни паттерн Adapter

Паттерн Adapter в C++ используется для приведения интерфейса одного класса к интерфейсу, ожидаемому клиентом. Это позволяет классам с несовместимыми интерфейсами работать вместе.

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

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


#include <iostream>

// Целевой интерфейс
class Target {
public:
virtual void request() const {
std::cout << "Target request" << std::endl;
}
};

// Класс с несовместимым интерфейсом
class Adaptee {
public:
void specificRequest() const {
std::cout << "Adaptee specific request" << std::endl;
}
};

// Адаптер, который делает интерфейс Adaptee совместимым с Target
class Adapter : public Target {
private:
Adaptee& adaptee;
public:
Adapter(Adaptee& a) : adaptee(a) {}

void request() const override {
adaptee.specificRequest();
}
};

int main() {
Adaptee adaptee;
Adapter adapter(adaptee);
adapter.request(); // Вывод: Adaptee specific request

return 0;
}


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

Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥2
🔥 Как использовать ссылки в качестве параметров функций?

Ссылки в C++ позволяют передавать параметры в функции без копирования, что экономит память и время. Ссылки обеспечивают доступ к оригинальному объекту, позволяя функции изменять его состояние.

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


#include <iostream>

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

int main() {
int num = 5;
increment(num);
std::cout << num << std::endl; // 6

return 0;
}


Ссылки также могут быть константными, если требуется защитить данные от изменений. Константные ссылки const & позволяют передавать большие объекты без копирования, сохраняя их неизменными:


#include <iostream>

void printValue(const int& value) {
std::cout << value << std::endl;
}

int main() {
int num = 10;
printValue(num); // 10

return 0;
}


Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥21
🔥 Как работают перечисления?

Перечисления (enums) в C++ представляют собой способ создания именованных констант, которые облегчают чтение и поддержку кода. Они позволяют группировать связанные значения под одним именем, что делает код более понятным и безопасным.

В C++ существует два типа перечислений: старые перечисления (unscoped enums) и новые перечисления (scoped enums), введенные в C++11.

Старые перечисления объявляются с помощью ключевого слова enum и создают набор целочисленных констант, которые автоматически увеличиваются на единицу, начиная с нуля, если не указано иное:


enum Color { Red, Green, Blue };
Color c = Red;


Новые перечисления объявляются с использованием enum class и обеспечивают лучшую область видимости и типобезопасность. Значения таких перечислений неявно не преобразуются в целые числа:


enum class Color { Red, Green, Blue };
Color c = Color::Red;


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

Ставь 👍, если было полезно!
Еще больше ответов для подготовки к собеседованиям на сайте 👈
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1121
💡Директива #include в C++ используется для подключения заголовочных файлов в программу. Она позволяет компилятору вставлять содержимое указанного файла в точку, где находится директива. Это необходимо для использования функций, классов и других элементов, определённых в подключаемых файлах.

Существует два типа #include: с угловыми скобками <...> для стандартных библиотек и с кавычками "..." для пользовательских файлов. Это упрощает управление кодом и способствует его повторному использованию, обеспечивая модульность и структурированность программы.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍111
Std::list и std::vector — это контейнеры из стандартной библиотеки C++, но они имеют разные характеристики и предназначения.

1️⃣ std::vector — это динамический массив, который обеспечивает быстрый доступ к элементам по индексу и эффективное добавление элементов в конец. Однако вставка или удаление элементов в середине может быть медленной, так как требует сдвига элементов.

2️⃣ std::list — это двусвязный список, который позволяет быстро вставлять и удалять элементы в любом месте, но доступ к элементам по индексу медленный, так как требуется последовательный обход.

ℹ️Выбор между ними зависит от конкретных требований к производительности и операциям.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥41
ℹ️Подписывайся на наши новые каналы!

🖥 JS собеседования
🖥 Backend собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
Namespaces используются для организации кода и предотвращения конфликтов имен. Они позволяют группировать связанные классы, функции и переменные, что особенно полезно в больших проектах или при использовании сторонних библиотек.

namespace MyNamespace {
int myVariable;
void myFunction() {
// код
}
}


🔵Для доступа к элементам namespace используется оператор ::

MyNamespace::myFunction();


🔵Можно использовать директиву using, чтобы упростить доступ

using namespace MyNamespace;
myFunction();

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

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍101
🔥Приоритет операторов в C++ определяет порядок, в котором выполняются операции в выражении. Операторы с более высоким приоритетом выполняются раньше, чем операторы с более низким приоритетом. Например, в выражении 3 + 4 * 5 сначала выполняется умножение, а затем сложение, так как оператор * имеет более высокий приоритет, чем +.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥1😎1
Множественное наследование - это механизм, позволяющий классу наследовать свойства и методы от нескольких базовых классов одновременно.

При множественном наследовании производный класс получает все члены всех своих базовых классов. Это дает возможность комбинировать функциональность разных классов в одном.

Пример синтаксиса:

class Derived : public Base1, public Base2 {
// тело класса
};


Основные проблемы множественного наследования:
〰️ Ромбовидное наследование (diamond problem)
〰️ Неоднозначность при одинаковых именах членов базовых классов
〰️ Увеличение сложности кода

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

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥1
✏️ std::cout и std::cin — это стандартные потоки ввода и вывода. Они определены в библиотеке <iostream>.

1️⃣ std::cout используется для вывода данных на стандартный поток вывода, обычно это консоль. Пример использования: std::cout << "Hello, World!";.

2️⃣ std::cin предназначен для ввода данных с клавиатуры. Он считывает данные из стандартного потока ввода. Пример: int x; std::cin >> x;.

Оба потока являются частью пространства имен std, поэтому перед их использованием необходимо либо указать using namespace std;, либо явно использовать префикс std::.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥5
Статические переменные — это переменные, которые сохраняют своё значение между вызовами функции или в пределах класса. Они инициализируются только один раз и существуют на протяжении всего времени выполнения программы.

👉 В функции статическая переменная сохраняет своё значение между вызовами:

#include <iostream>

void counter() {
static int count = 0;
count++;
std::cout << "Count: " << count << std::endl;
}

int main() {
counter(); // Вывод: Count: 1
counter(); // Вывод: Count: 2
return 0;
}


👉 В классе статическая переменная принадлежит классу, а не объекту, и общая для всех экземпляров.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61🔥1
💡Паттерны проектирования — это повторяющиеся решения общих проблем проектирования в программировании. Они предоставляют шаблоны для структурирования кода, улучшая его читаемость, расширяемость и поддержку.

Существуют три основные категории паттернов: порождающие, структурные и поведенческие. Порождающие паттерны, такие как Singleton и Factory, управляют созданием объектов. Структурные, например, Adapter и Composite, определяют способы построения классов и объектов. Поведенческие, такие как Observer и Strategy, описывают взаимодействие между объектами.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍111
🔥 noexcept — это спецификатор, который указывает, что функция не выбрасывает исключений. Использование noexcept может улучшить производительность, так как компилятор может оптимизировать код, зная, что исключения не возникнут. Это также помогает в обеспечении безопасности исключений, особенно в деструкторах и операциях перемещения.

void safeFunction() noexcept {
// Код, который не выбрасывает исключений
}

void riskyFunction() {
throw std::runtime_error("Ошибка");
}

int main() {
safeFunction(); // Безопасно
// riskyFunction(); // Это вызовет исключение
}


Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥2
std::map и std::set — это контейнеры из стандартной библиотеки C++, которые предоставляют эффективные способы хранения и управления данными.

1⃣ std::map — это ассоциативный контейнер, который хранит пары "ключ-значение". Он автоматически сортирует элементы по ключам и обеспечивает быстрый доступ к значениям по ключу. Пример использования:

#include <map>
#include <iostream>

std::map<int, std::string> myMap;
myMap[1] = "one";
myMap[2] = "two";

for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}


2⃣ std::set — это контейнер, который хранит уникальные элементы в отсортированном порядке. Он предоставляет быстрые операции вставки, удаления и поиска. Пример:

#include <set>
#include <iostream>

std::set<int> mySet = {1, 2, 3};
mySet.insert(4);

for (int n : mySet) {
std::cout << n << std::endl;
}


✔️ Оба контейнера используют деревья поиска для обеспечения логарифмической сложности операций.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥2
🔹Указатель this представляет собой неявный параметр, передаваемый в нестатические член-функции класса. Он указывает на текущий экземпляр объекта, для которого вызывается метод. Это позволяет функции обращаться к членам объекта и различать их от локальных переменных или параметров с одинаковыми именами.

🔹 Использование this особенно полезно при необходимости вернуть объект из метода, реализовать метод цепочки вызовов или различать члены класса от параметров функции. Например:

class MyClass {
public:
int value;

void setValue(int value) {
this->value = value;
}
};


🔹В этом примере this->value обозначает член класса value, тогда как параметр функции также называется value. Без использования this компилятор не сможет различить их.

🔹Кроме того, this позволяет реализовать возврат текущего объекта из метода:

MyClass& increment() {
this->value++;
return *this;
}


Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍131🤔1
🔸Inline-функции — это функции, которые компилятор пытается вставить непосредственно в место вызова, чтобы избежать накладных расходов на вызов функции. Это может улучшить производительность, особенно для небольших функций, которые часто вызываются. Для объявления функции inline используется ключевое слово inline.

inline int add(int a, int b) {
return a + b;
}


🔸Компилятор может игнорировать inline, если функция слишком сложная. Inline-функции должны быть определены в заголовочных файлах, чтобы компилятор имел доступ к их коду при компиляции каждого модуля.

Ставь 👍, если было полезно!
Больше ответов на сайте 👈

✈️ С++ собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91