🎯 Добро пожаловать в “C++?” — канал о подготовке программистов C++ к собеседованиям!
Здесь ты найдёшь:
🧠 Реальные вопросы из интервью — от junior до senior
💻 Разборы задач и кода
⚙️ Советы и типичные ловушки на собеседованиях
Всё — кратко, по делу, с примерами кода.
📘 Подписывайся, чтобы каждый день становиться ближе к офферу 💼
💬 Хочешь разбор конкретного вопроса? Напиши его в комментариях, а мы подготовим соответствующий пост 👇
Здесь ты найдёшь:
🧠 Реальные вопросы из интервью — от junior до senior
💻 Разборы задач и кода
⚙️ Советы и типичные ловушки на собеседованиях
Всё — кратко, по делу, с примерами кода.
📘 Подписывайся, чтобы каждый день становиться ближе к офферу 💼
💬 Хочешь разбор конкретного вопроса? Напиши его в комментариях, а мы подготовим соответствующий пост 👇
🧠 Вопрос из реального интервью для понимания отличий языка C++ от C (junior):
👉 Чем отличается
Ответ тезисно:
2️⃣
3️⃣
4️⃣
5️⃣
#cpp_question #cpp_tips
👉 Чем отличается
new от malloc?Ответ тезисно:
1️⃣ new/delete используется в C++, а malloc/free — в C2️⃣
new вызывает конструктор, malloc — нет. 3️⃣
new возвращает указатель конкретного типа, malloc — void*. 4️⃣
new выбрасывает исключение std::bad_alloc, malloc — возвращает nullptr. 5️⃣
delete вызывает деструктор, free — просто освобождает память.#cpp_question #cpp_tips
✅ Ответ к задаче из предыдущего поста:
lvalue rvalue
❗️Пояснения:
a — именованная переменная → lvalue
10 — временное значение → rvalue
🧠 На интервью часто спрашивают:
Ответ:
lvalue имеет адрес и может стоять слева от =, rvalue — временное значение, которое можно только читать.
#cpp_question #cpp_challenge
❗️Пояснения:
a — именованная переменная → lvalue
10 — временное значение → rvalue
🧠 На интервью часто спрашивают:
Что такое lvalue и rvalue?
Ответ:
lvalue имеет адрес и может стоять слева от =, rvalue — временное значение, которое можно только читать.
#cpp_question #cpp_challenge
⚙️Простой алгоритм для реализации на собеседовании (junior)
🔎 Бинарный поиск
Сложность: O(log n)
❗️Вопрос на собеседовании:
Ответ: поведение непредсказуемо — алгоритм применим только к отсортированным массивам.
#cpp_algo #cpp_question
🔎 Бинарный поиск
Сложность: O(log n)
❗️Вопрос на собеседовании:
Что будет, если массив не отсортирован?
Ответ: поведение непредсказуемо — алгоритм применим только к отсортированным массивам.
#cpp_algo #cpp_question
💬 Простой вопрос про ООП (Объектно-Ориентированное Программирование) (junior)
Пример виртуального деструктора:
✅ Ответ: Если в базовом классе нет виртуального деструктора, при удалении через Base* вызывается только базовый деструктор, а деструктор наследника — нет → утечка памяти!
#cpp_question
Зачем нужен виртуальный деструктор?
Пример виртуального деструктора:
struct Base
{
virtual ~Base() = default;
};
✅ Ответ: Если в базовом классе нет виртуального деструктора, при удалении через Base* вызывается только базовый деструктор, а деструктор наследника — нет → утечка памяти!
#cpp_question
🧠 Частый вопрос на знание ключевых слов языка
Что делает ключевое слово explicit? (junior)
📘 Ответ: explicit запрещает неявные преобразования.
Используй его, чтобы избежать случайного вызова конструктора при присваивании.
#cpp_question #cpp_tips
Что делает ключевое слово explicit? (junior)
struct Client {
explicit Client(int x) {}
};
Client a = 5; // ❌ ошибка
Client b(5); // ✅ ок📘 Ответ: explicit запрещает неявные преобразования.
Используй его, чтобы избежать случайного вызова конструктора при присваивании.
#cpp_question #cpp_tips
💬 auto — зло или добро?
💡 Тема: Осознанное использование auto
🎯 Цель: показать, как auto влияет на читаемость, безопасность и оптимизацию
Когда-то auto использовали для вывода типа переменной, теперь же — почти повсюду.
Но стоит ли всегда полагаться на него?
⚙️ Пример 1 — где auto реально помогает
Здесь auto делает код чище и читабельнее.
Без него пришлось бы писать много нечитабельного кода:
⚠️ Пример 2 — где auto вредит
На первый взгляд всё нормально, но sum — это double, а не int.
Если заменить 0.0 на 0, тип поменяется — и можно незаметно получить другую арифметику.
❗️ Иногда auto скрывает ошибки типов, особенно с const, &, && и decltype.
✅ Используй auto, когда:
1) Тип очевиден из правой части;
2) Хочешь избежать дублирования и повысить читаемость.
❌ Не используй auto, когда:
1) Важно сохранить const / &;
2) Выражение возвращает временный объект с неочевидным типом;
3) Тип влияет на поведение.
#cpp_tips
💡 Тема: Осознанное использование auto
🎯 Цель: показать, как auto влияет на читаемость, безопасность и оптимизацию
Когда-то auto использовали для вывода типа переменной, теперь же — почти повсюду.
Но стоит ли всегда полагаться на него?
⚙️ Пример 1 — где auto реально помогает
std::unordered_map<std::string, std::vector<int>> data;
// ...
for (auto& [key, values] : data) {
std::cout << key << " → " << values.size() << "\n";
}
Здесь auto делает код чище и читабельнее.
Без него пришлось бы писать много нечитабельного кода:
for (std::pair<const std::string, std::vector<int>>& entry : data)
⚠️ Пример 2 — где auto вредит
std::vector<int> v = {1, 2, 3};
auto sum = std::accumulate(v.begin(), v.end(), 0.0);На первый взгляд всё нормально, но sum — это double, а не int.
Если заменить 0.0 на 0, тип поменяется — и можно незаметно получить другую арифметику.
❗️ Иногда auto скрывает ошибки типов, особенно с const, &, && и decltype.
✅ Используй auto, когда:
1) Тип очевиден из правой части;
2) Хочешь избежать дублирования и повысить читаемость.
❌ Не используй auto, когда:
1) Важно сохранить const / &;
2) Выражение возвращает временный объект с неочевидным типом;
3) Тип влияет на поведение.
#cpp_tips
✔️ decltype(auto) — ответ на вопрос:
✨ decltype(auto) — это auto, который уважает тип
Разница: decltype(auto) сохраняет точный тип выражения, включая &, const и &&.
💡 Итог:
Используй decltype(auto), если не хочешь терять ссылки и cv квалификаторы
Как сохранить точный тип выражения, используя ключевое слово auto ?
✨ decltype(auto) — это auto, который уважает тип
int x = 10;
auto f1() {
return x;
} // возвращает int (копию)
decltype(auto) f2() {
return x;
} // возвращает int&
Разница: decltype(auto) сохраняет точный тип выражения, включая &, const и &&.
💡 Итог:
Используй decltype(auto), если не хочешь терять ссылки и cv квалификаторы
⚙️ Современные ключевые слова C++: поведение, ABI (Application Binary Interface) и контроль компиляции
На собеседованиях спрашивают о назначении и применении различных модификаторов, квалификаторов и ключевых слов. Необходимо быстро ориентироваться и понимать, для чего они используются в коде. Разберем примеры таких слов.
🔹 explicit
Что делает:
Запрещает неявные вызовы конструктора или оператора преобразования.
Зачем нужно:
Чтобы не происходило неожиданных преобразований при передаче аргументов.
🧩 Влияет: только на синтаксис, не меняет ABI.
🔹 default
Что делает:
Поручает компилятору сгенерировать дефолтную реализацию конструктора, оператора или деструктора.
💡 Используется, если нужны “нормальные” поведенческие функции после переопределения других.
📦 Не меняет ABI, делает класс тривиальным.
🔹 delete
Что делает:
Запрещает генерацию функции компилятором.
🧱 Полезно для контроля вызовов.
⚙️ Меняет ABI — удалённая функция исключается из таблицы символов.
🔹 constexpr
Что делает:
Позволяет вычислять выражение во время компиляции, если аргументы известны на этапе компиляции.
💡 С constexpr компилятор проверяет чистоту функции и детерминированность.
⚙️ Влияет на оптимизацию и инициализацию глобальных объектов.
🔹 consteval
Что делает:
Обязывает выполнить функцию только на этапе компиляции.
⚠️ Нельзя вызвать во время выполнения.
📦 Часто используется в метапрограммировании и проверках.
🔹 constinit
Что делает:
Гарантирует compile-time инициализацию, но функция может быть не constexpr.
💡 Позволяет избежать “order of initialization” багов между глобальными объектами.
🔹 noexcept
Что делает:
Объявляет, что функция не выбрасывает исключений.
⚙️ Меняет ABI:
void f() и void f() noexcept — разные сигнатуры на уровне линковки.
🔹 override
Что делает:
Проверяет, что функция реально переопределяет виртуальную из базового класса.
⚙️ Не влияет на ABI, но предотвращает ошибки переопределения.
🔹 final
Что делает:
Запрещает дальнейшее переопределение или наследование.
💡 Помогает компилятору оптимизировать виртуальные вызовы.
🔹 using
Что делает:
Способ унаследовать конструкторы или импортировать перегрузки.
💡 Используется в шаблонах и при работе с зависимыми именами.
🧩 Не влияет на ABI. Используйте аккуратно, не рекомендуется к повсеместному использованию
🔹 concept и requires (C++20)
Что делают:
Определяют ограничения для шаблонов, чтобы типы соответствовали ожидаемым свойствам.
🧠 Делают код предсказуемым при ошибках компиляции.
✅ Мы разобрали основные ключевые слова, модификаторы и квалификаторы C++. Сохраняйте и делитесь с друзьями. Если хотите еще разборов, пишите в комментариях, а мы подготовим новый пост👇
На собеседованиях спрашивают о назначении и применении различных модификаторов, квалификаторов и ключевых слов. Необходимо быстро ориентироваться и понимать, для чего они используются в коде. Разберем примеры таких слов.
🔹 explicit
Что делает:
Запрещает неявные вызовы конструктора или оператора преобразования.
Зачем нужно:
Чтобы не происходило неожиданных преобразований при передаче аргументов.
struct S {
explicit S(int x) {} // нельзя вызвать S s = 10;
};
S a(10); // ✅
S b = 10; // ❌ error: explicit constructor🧩 Влияет: только на синтаксис, не меняет ABI.
🔹 default
Что делает:
Поручает компилятору сгенерировать дефолтную реализацию конструктора, оператора или деструктора.
struct Foo {
Foo() = default; // явно разрешаем
~Foo() = default; // деструктор по умолчанию
};💡 Используется, если нужны “нормальные” поведенческие функции после переопределения других.
📦 Не меняет ABI, делает класс тривиальным.
🔹 delete
Что делает:
Запрещает генерацию функции компилятором.
struct Bar {
Bar(int) = delete; // нельзя создать из int
Bar() = default;
};🧱 Полезно для контроля вызовов.
⚙️ Меняет ABI — удалённая функция исключается из таблицы символов.
🔹 constexpr
Что делает:
Позволяет вычислять выражение во время компиляции, если аргументы известны на этапе компиляции.
constexpr int square(int x) {
return x * x;
}
constexpr int n = square(5); // вычисляется на этапе компиляции💡 С constexpr компилятор проверяет чистоту функции и детерминированность.
⚙️ Влияет на оптимизацию и инициализацию глобальных объектов.
🔹 consteval
Что делает:
Обязывает выполнить функцию только на этапе компиляции.
consteval int id() {
return 42;
}
constexpr int v = id(); // только compile-time⚠️ Нельзя вызвать во время выполнения.
📦 Часто используется в метапрограммировании и проверках.
🔹 constinit
Что делает:
Гарантирует compile-time инициализацию, но функция может быть не constexpr.
constinit int x = 42;
💡 Позволяет избежать “order of initialization” багов между глобальными объектами.
🔹 noexcept
Что делает:
Объявляет, что функция не выбрасывает исключений.
void f() noexcept; // не может выбросить throw
void g() noexcept(false); // может
⚙️ Меняет ABI:
void f() и void f() noexcept — разные сигнатуры на уровне линковки.
🔹 override
Что делает:
Проверяет, что функция реально переопределяет виртуальную из базового класса.
struct Base {
virtual void foo();
};
struct Derived : Base {
void foo() override; // ✅
void bar() override; // ❌ error: не виртуальная в базовом
};⚙️ Не влияет на ABI, но предотвращает ошибки переопределения.
🔹 final
Что делает:
Запрещает дальнейшее переопределение или наследование.
struct A final {}; // нельзя наследовать
struct B {
virtual void f() final;
}; // нельзя переопределять💡 Помогает компилятору оптимизировать виртуальные вызовы.
🔹 using
Что делает:
Способ унаследовать конструкторы или импортировать перегрузки.
using number_t = int; // синоним для int
number_t a = 42;
struct A {
void foo(int);
};
struct B : A {
using A::foo;
}; // импорт перегрузки
💡 Используется в шаблонах и при работе с зависимыми именами.
🧩 Не влияет на ABI. Используйте аккуратно, не рекомендуется к повсеместному использованию
🔹 concept и requires (C++20)
Что делают:
Определяют ограничения для шаблонов, чтобы типы соответствовали ожидаемым свойствам.
#include<concept>
template <typename M>
concept Integral = std::integral<M>; // M должен быть целочисленным типом
template<typename T>
concept Addable = requires(T a, T b) { a + b; };
template<Addable T>
T sum(T a, T b) { return a + b; }
🧠 Делают код предсказуемым при ошибках компиляции.
✅ Мы разобрали основные ключевые слова, модификаторы и квалификаторы C++. Сохраняйте и делитесь с друзьями. Если хотите еще разборов, пишите в комментариях, а мы подготовим новый пост👇
👇 Попробуйте решить серию интересных быстрых задач с собеседования уровень junior
#cpp_challenge
🧩 Задача 1 — "Кто изменит x?"
#cpp_challenge
🧩 Задача 1 — "Кто изменит x?"
int x = 10;
auto f = [x]() mutable {
++x;
return x;
};
std::cout << f() << " " << x << "\n";
💭 Как думаете, что выведет программа?
Anonymous Quiz
0%
10 11
0%
11 11
50%
Ошибка компиляции
50%
11 10
⚙️ Задача 2 — "Кто здесь const?"
int n = 42;
const int& r = n;
auto x = r;
auto& y = r;
++n;
std::cout << x << " " << y << "\n";
🧠 Попробуйте понять, что выведет программа:
Anonymous Quiz
33%
43 43
33%
42 42
17%
42 43
17%
Ошибка компиляции
⚡️ Задача 3 — "Кто владелец строки?"
std::string getName() {
return "Bjarne";
}
auto&& name = getName();
std::cout << name << "\n";⚙️ Что выведет программа?
Anonymous Quiz
21%
Неопределённый вывод
50%
Выведет Bjarne
14%
Висячая ссылка
14%
Ошибка компиляции
⚠️ Самый последний способ не будет компилироваться, так как перестановка полей для инициализации класса не допустима.
struct Entity
{
int x = 0, y = 0;
};
int main()
{
Entity entity_1;
Entity entity_2(2);
Entity entity_3(3, 3);
Entity entity_4 { .x = 4 };
Entity entity_5 { .x = 5, .y = 5 };
Entity entity_6 { .y = 6 };
// Entity entity_7 { .y = 7, .x = 7 }; // error
}
#cpp_tips
Please open Telegram to view this post
VIEW IN TELEGRAM