TGViewer
Channel Public Channel
C/C++ | Вопросы собесов

C/C++ | Вопросы собесов

@easy_c_plus

Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy

Контакт для рекламы: @sendme_ads
Subscribers
4.2K
Photos
37
Videos
1
Links
1.6K

Showing posts older than #2198 · Back to latest

Older Posts 20 shown
Post #2195 802
🤔 Что представляют из себя статические библиотеки?

Статические библиотеки — это файлы, содержащие скомпилированный код и связанные функции, которые компилятор включает в конечный исполняемый файл. Они имеют расширение .lib (Windows) или .a (Linux) и увеличивают размер программы, но не требуют наличия библиотеки на целевой системе.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
  • 🔥 1
Post #2194 830
🤔 Как называется возможность вызова функции без явного указания namespace?

Такую возможность называют ADL (Argument-Dependent Lookup) или Koenig Lookup. Компилятор автоматически ищет функцию в пространстве имен аргумента, если оно не указано явно.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2192 852
🤔 При помощи чего сохраняются exception?

Используется std::exception_ptr, который может сохранять и передавать исключения между потоками.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2191 848
🤔 Что такое ODR?

ODR (One Definition Rule) – это правило одной определения в C++, которое запрещает множественное определение одной и той же сущности в программе.
ODR применяется к:
Переменным
Функциям
Классам
Если ODR нарушено, получим ошибку компоновки (linker error, multiple definition).

🚩Основные правила ODR

Переменная может быть определена только один раз
// a.cpp
int x = 42; // Определение переменной

// b.cpp
int x = 42; // ❌ Ошибка компоновки: повторное определение x


Решение: Использовать extern в заголовочном файле.
// common.h
extern int x; // Объявление

// a.cpp
#include "common.h"
int x = 42; // Определение (только в одном месте)

// b.cpp
#include "common.h"


Функция может быть определена только один раз (если не inline)
// a.cpp
void foo() { } // Определение функции

// b.cpp
void foo() { } // ❌ Ошибка: повторное определение


Решение: Использовать inline или объявить в header, но определить в .cpp.
// common.h
inline void foo() { } // ✅ OK, `inline` разрешает множественные определения


Класс можно определить только один раз
// a.h
struct A {
int x;
};

// a.h включён в два файла -> ❌ Ошибка "redefinition of struct A"


Решение: Использовать #pragma once или #ifndef
// a.h
#pragma once // ✅ Защита от двойного включения
struct A {
int x;
};


constexpr нарушает ODR при разных значениях
// common.h
constexpr int getValue() { return 10; }

// a.cpp
int a = getValue(); // 10

// b.cpp
constexpr int getValue() { return 20; } // ❌ Ошибка: разные определения


Ставь 👍 и забирай 📚 Базу знаний
  • 👍 1
  • 💊 1
Post #2189 740
🤔 Какие есть операторы приведения типов?

1. static_cast: Для явного и безопасного приведения типов, известных на этапе компиляции.
2. dynamic_cast: Для приведения указателей или ссылок в иерархии классов с проверкой типов во время выполнения.
3. const_cast: Для снятия или добавления const и volatile квалификаторов.
4. reinterpret_cast: Для низкоуровневого преобразования указателей или других типов без проверки безопасности.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2188 700
🤔 Какая сложность удаления в list и vector по итератору?

Удаление по итератору имеет сложность O(1) для списка, поскольку он реализован как двусвязный список и позволяет удалять элементы без сдвига других. Для вектора сложность удаления по итератору составляет O(n), так как элементы в памяти расположены последовательно, и после удаления требуется сдвиг всех последующих элементов, что требует линейного времени.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2187 715
🤔 Как работает виртуальность в C++?

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

🚩Виртуальные функции

Виртуальная функция определяется в базовом классе с ключевым словом virtual. Производный класс может переопределить эту функцию.
class Base {
public:
virtual void display() const {
std::cout << "Display from Base" << std::endl;
}
};

class Derived : public Base {
public:
void display() const override {
std::cout << "Display from Derived" << std::endl;
}
};


🚩Как работает vtable и vptr

🟠vtable (виртуальная таблица)
Это таблица указателей на виртуальные функции класса. Каждый класс, содержащий виртуальные функции, имеет свою собственную vtable. В vtable хранятся адреса функций, которые должны быть вызваны для объектов данного класса.

🟠vptr (указатель на vtable)
Это скрытый указатель в каждом объекте класса, содержащего виртуальные функции. Он указывает на vtable соответствующего класса. Когда объект создается, vptr инициализируется, указывая на vtable его класса.

#include <iostream>

class Base {
public:
virtual void display() const {
std::cout << "Display from Base" << std::endl;
}
virtual void show() const {
std::cout << "Show from Base" << std::endl;
}
};

class Derived : public Base {
public:
void display() const override {
std::cout << "Display from Derived" << std::endl;
}
};

int main() {
Base* b = new Derived();
b->display(); // Вызовет Derived::display() благодаря vtable
b->show(); // Вызовет Base::show() поскольку она не переопределена

delete b;
return 0;
}


🚩Процесс вызова виртуальных функций

🟠При компиляции
Компилятор создает vtable для каждого класса, содержащего виртуальные функции. Компилятор также добавляет скрытый vptr в каждый объект класса, который инициализируется для указания на соответствующую vtable.

🟠При выполнении
Когда вызывается виртуальная функция через указатель или ссылку на базовый класс, программа использует vptr для доступа к vtable и вызова правильной версии функции. Это обеспечивает динамическое разрешение вызова функции (runtime polymorphism).

🚩Полиморфизм и наследование

Полиморфизм позволяет использовать базовые указатели или ссылки для работы с производными объектами, что делает код более гибким и расширяемым.
void callDisplay(const Base& obj) {
obj.display();
}

int main() {
Base b;
Derived d;

callDisplay(b); // Вызовет Base::display()
callDisplay(d); // Вызовет Derived::display()

return 0;
}


Ставь 👍 и забирай 📚 Базу знаний
Post #2186 624
🤔 Сложность операций с vector и list

Для vector добавление элемента в конец имеет сложность O(1) в среднем, но при перераспределении памяти — O(n). Удаление и вставка в произвольное место занимают O(n), так как элементы необходимо сдвигать. Для list добавление и удаление имеют сложность O(1), но доступ по индексу — O(n), так как требуется последовательный обход элементов.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2185 719
🤔 Коллизия - когда для разных ключей получается одно и тоже хэш значение?

В контексте хеш-таблиц и хеш-функций коллизия возникает, когда два разных входных значения (ключа) генерируют одно и то же хеш-значение. Это является фундаментальной проблемой в хеш-таблицах, поскольку идея хеширования заключается в эффективном размещении и извлечении данных с использованием хеш-кода как индекса в массиве или списке.

🚩Причины возникновения

🟠Ограниченное количество возможных хеш-значений
Поскольку количество возможных хеш-значений фиксировано (и обычно меньше, чем количество возможных ключей), статистически неизбежно, что разные ключи будут иметь одинаковые хеш-значения.
🟠Неидеальные хеш-функции
Хеш-функции могут не равномерно распределять хеш-значения, что увеличивает вероятность коллизий.

🚩Способы решения

🟠Цепочки (Chaining)
В этом методе каждая ячейка хеш-таблицы содержит указатель на список (или другую структуру данных, например, связный список), которые хранят все элементы, имеющие одинаковый хеш. Это простой и эффективный метод, но может потребовать больше памяти и времени при обращении к элементам.

🟠Открытая адресация (Open Addressing)
Включает в себя методы, такие как линейное пробирование, квадратичное пробирование и двойное хеширование. При возникновении коллизии метод находит следующую свободную ячейку в таблице для размещения нового элемента.

🟠Двойное хеширование (Double Hashing)
Использует вторую хеш-функцию для определения интервала между пробами, уменьшая вероятность коллизий, которые происходят при первичном хешировании.

Ставь 👍 и забирай 📚 Базу знаний
Post #2184 693
🤔 Какая сложность работы с кучей?

Работа с кучей (heap) в алгоритмах обычно имеет временную сложность O(log n) для операций вставки и удаления, т.к. элементы необходимо сравнивать и переставлять для поддержания свойств кучи.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2182 747
🤔 Какая есть оптимизация в строках С++?

Стандартный класс std::string в C++ имеет несколько механизмов оптимизации для повышения производительности и уменьшения расхода памяти. Рассмотрим основные из них.

🟠Small String Optimization (SSO) – Оптимизация малых строк
Если строка маленькая (обычно до 15-23 байт, зависит от реализации), std::string не выделяет динамическую память, а хранит символы прямо внутри объекта std::string.
Обычно std::string содержит:
- Указатель на динамическую память
- Размер строки
- Вместимость (capacity)
Но если строка короткая, память не выделяется в куче (heap), а данные хранятся прямо внутри объекта std::string.
#include <iostream>
#include <string>

int main() {
std::string small = "Hello"; // Использует SSO
std::string large = "This is a very long string that will not fit SSO"; // Динамическая память

std::cout << "Small string: " << small << "\n";
std::cout << "Large string: " << large << "\n";
}


🟠Copy-on-Write (COW) – Оптимизация копирования (устарела)
Раньше (до C++11) std::string использовал технику Copy-on-Write (COW), где несколько строк могли разделять одну и ту же память, пока одна из них не изменялась.
Почему отказались?
Не потокобезопасно (если один поток меняет строку, другой может получить неожиданные данные). В C++11 было добавлено std::move, которое делает копирование дешевле. SSO делает COW менее нужной.
std::string a = "Hello";
std::string b = a; // Копия не создается, оба указывают на одну память
b[0] = 'X'; // Теперь создаётся отдельная копия


🟠Move Semantics – Семантика перемещения (C++11)
Вместо дорогостоящего копирования std::string теперь можно перемещать с помощью std::move(), передавая владение ресурсом без копирования.
#include <iostream>
#include <string>

int main() {
std::string a = "Hello, world!";
std::string b = std::move(a); // Перемещение, a становится пустой
std::cout << "b: " << b << "\n"; // "Hello, world!"
}


🟠Reserve() – Избегание частых выделений памяти
Если заранее известно, сколько символов потребуется, можно использовать .reserve(size), чтобы избежать многократных перевыделений памяти.
std::string str;
str.reserve(100); // Сразу выделяет память на 100 символов
for (int i = 0; i < 100; i++) {
str += 'a'; // Не перевыделяет память 100 раз
}


Ставь 👍 и забирай 📚 Базу знаний
Post #2180 662
🤔 Какая будет сложность удаления элемента с начала в vector?

Удаление элемента с начала вектора в C++ имеет временную сложность O(n), так как все элементы после удаляемого необходимо переместить ближе к началу вектора.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2179 810
🤔 Вызов function call для конструктора и деструктора?

В C++ конструктор вызывается автоматически при создании объекта, а деструктор – при его уничтожении. Однако, если говорить о вызове конструктора и деструктора как function call (операция ()), то такой вызов невозможен напрямую, потому что конструкторы и деструкторы не являются обычными функциями.

🚩Вызов конструктора (function call)

Конструктор вызывается только через создание объекта
class A {
public:
A() { std::cout << "Конструктор A\n"; }
};

int main() {
A obj; // Автоматический вызов конструктора
}


Нельзя вызвать конструктор явно как функцию. Попытка вызвать конструктор напрямую приведет к ошибке
A(); // ❌ Ошибка: нельзя вызвать конструктор как обычную функцию


Можно вручную вызвать конструктор через placement new
#include <iostream>
#include <new>

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

int main() {
char buffer[sizeof(A)]; // Выделяем сырую память под объект
A* obj = new (buffer) A; // Вызываем конструктор вручную (placement new)

obj->~A(); // Вызываем деструктор вручную

return 0;
}


🚩Вызов деструктора (function call)

Деструктор вызывается автоматически при уничтожении объекта
class A {
public:
~A() { std::cout << "Деструктор A\n"; }
};

int main() {
A obj; // Деструктор вызовется автоматически при выходе из `main`
}


Можно вызвать деструктор вручную, но это редко нужно. Деструктор можно вызвать явно, используя ~ИмяКласса()
A obj;
obj.~A(); // Вызов деструктора вручную (обычно не нужен)


Деструктор обязательно вызывается вручную при new. Если объект создается через new, то его нужно удалить вручную через delete, иначе будет утечка памяти:
A* ptr = new A();
delete ptr; // Автоматически вызывает деструктор


Вызов деструктора при placement new. Если объект создавался с placement new, то деструктор вызывается вручную
char buffer[sizeof(A)];
A* obj = new (buffer) A;

obj->~A(); // Явный вызов деструктора, так как delete не применяется


Ставь 👍 и забирай 📚 Базу знаний
Post #2177 762
🤔 Как работает быстрая сортировка?

Быстрая сортировка (quick sort) — это алгоритм, который рекурсивно делит массив на подмассивы на основе опорного элемента (pivot). Элементы, меньшие опорного, перемещаются в левую часть массива, а элементы, большие — в правую. Процесс продолжается рекурсивно для каждого подмассива, пока все элементы не будут отсортированы. В среднем случае быстрая сортировка имеет сложность O(n log n), но в худшем — O(n^2), если выбирать неудачный опорный элемент.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
  • 🔥 2
  • 👍 1
Post #2175 852
🤔 Какие есть уровни exception гарантий?

1. No-throw Guarantee: метод или операция не выбрасывает исключений. Пример: деструкторы.
2. Strong Guarantee: при выбросе исключения состояние объекта или программы остаётся неизменным.
3. Basic Guarantee: состояние объекта остаётся корректным, но изменения могут быть частичными.
4. No Guarantee: программа может оказаться в некорректном состоянии при исключении.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
  • 🔥 2
  • 👍 1
Post #2173 893
🤔 В unordered_set поиск — константа?

Поиск в unordered_set имеет среднюю сложность O(1), но в худшем случае при хеш-коллизиях может быть O(n).

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2171 1.05K
🤔 Как работает priority_queue?

priority_queue управляет элементами на основе их приоритетов, используя бинарную кучу: на вершине всегда элемент с наивысшим приоритетом, а операции добавления и удаления имеют сложность O(log n).

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
  • 💊 1
Post #2169 1.06K
🤔 Выбрасывание исключения из конструктора — это нормально?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
Post #2168 993
🤔 Как проверять равенство двух float?

Равенство двух float проверяется с учётом допустимой разницы (эпсилон), чтобы избежать ошибок из-за неточности представления:
∣a−b∣<ϵ, где ϵ — небольшое значение, например 10−610^{-6}.
Такой подход помогает корректно сравнивать близкие числа, которые могут отличаться в пределах допустимой погрешности.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
  • 👍 7
Post #2167 926
🤔 Когда начинают жить и умирают глобальные и локальные переменные в С++?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу знаний
  • 👍 8
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →