
- Главная
- Каталог
- Интернет технологии
- C/C++ | Вопросы собесов
C/C++ | Вопросы собесов
Разбираем вопросы с собеседований на С/С++ разработчика
Статистика канала
#include <iostream>
#include <vector>
class BadContainer {
std::vector<int> data;
public:
void add(int value) {
data.push_back(value); // push_back() может выбросить исключение
}
void print() {
for (int x : data) std::cout << x << " ";
std::cout << std::endl;
}
};
int main() {
BadContainer c;
c.add(1);
c.add(2);
c.add(3);
c.print(); // Вывод: 1 2 3
try {
c.add(42); // Может выбросить исключение (например, нехватка памяти)
} catch (...) {
std::cout << "Ошибка!\n";
}
c.print(); // ❌ Возможно, состояние испорчено!
}{}
🚩Как реализовать строгую гарантию?
Чтобы добиться строгой гарантии, используем Copy & Swap:
1. Создаём временный объект.
2. Выполняем изменения на временном объекте.
3. Если всё прошло успешно – меняем указатель (swap).
#include <iostream>
#include <vector>
class SafeContainer {
std::vector<int> data;
public:
void add(int value) {
std::vector<int> temp = data; // Создаём копию текущего состояния
temp.push_back(value); // Добавляем элемент в копию
std::swap(data, temp); // Если исключения не было, меняем данные
}
void print() {
for (int x : data) std::cout << x << " ";
std::cout << std::endl;
}
};
int main() {
SafeContainer c;
c.add(1);
c.add(2);
c.add(3);
c.print(); // Вывод: 1 2 3
try {
c.add(42); // Если тут исключение, объект не изменится
} catch (...) {
std::cout << "Ошибка!\n";
}
c.print(); // ✅ Вывод: 1 2 3 (не испорчен!)
}{}
🚩Где используется строгая гарантия?
Операции присваивания (operator=) с Copy & Swap
Методы стандартных контейнеров (std::vector::resize, std::map::insert)
Функции стандартной библиотеки (std::sort)
Изменения объектов с ресурсами (файлы, сокеты, память)
Ставь 👍 и забирай 📚 Базу знаний
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base constructor\n";
// Вызов виртуальной функции из конструктора
this->virtualFunction();
}
virtual ~Base() {
std::cout << "Base destructor\n";
// Вызов виртуальной функции из деструктора
this->virtualFunction();
}
virtual void virtualFunction() {
std::cout << "Base virtualFunction\n";
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor\n";
}
~Derived() override {
std::cout << "Derived destructor\n";
}
void virtualFunction() override {
std::cout << "Derived virtualFunction\n";
}
};
int main() {
Derived d;
return 0;
}{}
🤔 Вывод программы:
Base constructor
Base virtualFunction
Derived constructor
Derived destructor
Base destructor
Base virtualFunction{}
Ставь 👍 и забирай 📚 Базу знанийnew, но перед его удалением произошло исключение, деструктор не вызовется автоматически.
#include <iostream>
class A {
public:
A() { std::cout << "Конструктор A\n"; }
~A() { std::cout << "Деструктор A\n"; }
};
void func() {
A* obj = new A(); // Создаем объект динамически
throw std::runtime_error("Ошибка!"); // Исключение, объект утечет
delete obj; // Никогда не выполнится
}
int main() {
try {
func();
} catch (...) {
std::cout << "Исключение поймано\n";
}
}{}
Как исправить?
Использовать std::unique_ptr, который автоматически удаляет объект
#include <memory>
void func() {
std::unique_ptr<A> obj = std::make_unique<A>();
throw std::runtime_error("Ошибка!"); // Деструктор вызовется автоматически
}{}
🟠Локальные объекты, созданные `new` внутри `try`, но `catch` не обработал исключение
Если объект выделяется внутри try, но исключение не ловится в catch, программа завершится (std::terminate), и деструкторы не вызовутся.
void func() {
A* obj = new A();
throw std::runtime_error("Ошибка!"); // std::terminate()
delete obj;
}
int main() {
func(); // Исключение не ловится => программа аварийно завершится
}{}
Как исправить?
Нужно обрабатывать исключение на верхнем уровне
int main() {
try {
func();
} catch (...) {
std::cout << "Ошибка обработана\n";
}
}{}
🟠Исключение в конструкторе
Если исключение возникает в конструкторе, деструктор этого объекта не вызывается, но деструкторы уже созданных объектов будут вызваны.
class B {
public:
B() { std::cout << "Конструктор B\n"; }
~B() { std::cout << "Деструктор B\n"; }
};
class A {
public:
A() {
std::cout << "Конструктор A\n";
throw std::runtime_error("Ошибка в конструкторе A");
}
~A() { std::cout << "Деструктор A\n"; } // Никогда не вызовется!
};
int main() {
try {
B b;
A a; // Исключение в конструкторе A
} catch (...) {
std::cout << "Исключение обработано\n";
}
}{}
Вывод
Конструктор B
Конструктор A
Исключение обработано
Деструктор B{}
Как исправить?
- Использовать концепцию "умные указатели" (std::unique_ptr), чтобы ресурсы очищались автоматически.
- Переносить ресурсоемкие операции в отдельный метод (init()), который можно вызывать после конструктора.
🟠Исключение в деструкторе
Если деструктор объекта бросает исключение, это опасно, особенно если исключение возникло в момент обработки другого исключения.
class A {
public:
~A() {
std::cout << "Деструктор A\n";
throw std::runtime_error("Ошибка в деструкторе!"); // Ошибка
}
};
int main() {
try {
A a;
throw std::runtime_error("Основное исключение");
} catch (...) {
std::cout << "Исключение обработано\n";
}
}{}
Как исправить?
Деструкторы не должны выбрасывать исключения. Если исключение возможно, его следует перехватывать внутри деструктора
class A {
public:
~A() {
try {
throw std::runtime_error("Ошибка в деструкторе!");
} catch (...) {
std::cout << "Ошибка подавлена в деструкторе\n";
}
}
};{}
Ставь 👍 и забирай 📚 Базу знаний
class MyClass {
public:
MyClass() {}
};{}
🟠Параметризованный конструктор (Parameterized Constructor)
Принимает параметры для инициализации объекта.
class MyClass {
private:
int x;
public:
MyClass(int value) : x(value) {}
};{}
🟠Конструктор копирования (Copy Constructor)
Создает копию существующего объекта.
class MyClass {
private:
int x;
public:
MyClass(const MyClass &other) : x(other.x) {}
};{}
🟠Конструктор перемещения (Move Constructor)
Перемещает ресурсы из временного объекта.
class MyClass {
private:
int* data;
public:
MyClass(MyClass&& other) noexcept : data(other.data) {
other.data = nullptr;
}
};{}
🟠Делегирующий конструктор (Delegating Constructor)
Вызывает другой конструктор того же класса.
class MyClass {
private:
int x, y;
public:
MyClass(int value) : MyClass(value, 0) {}
MyClass(int value1, int value2) : x(value1), y(value2) {}
};{}
🟠Явный конструктор (Explicit Constructor)
Помечен explicit для предотвращения неявных преобразований.
class MyClass {
public:
explicit MyClass(int value) {}
};{}
Ставь 👍 и забирай 📚 Базу знанийОтзывы канала
- Добавлен: Сначала новые
- Добавлен: Сначала старые
- Оценка: По убыванию
- Оценка: По возрастанию
Каталог Телеграм-каналов для нативных размещений
C/C++ | Вопросы собесов — это Telegam канал в категории «Интернет технологии», который предлагает эффективные форматы для размещения рекламных постов в Телеграмме. Количество подписчиков канала в 4.3K и качественный контент помогают брендам привлекать внимание аудитории и увеличивать охват. Рейтинг канала составляет 5.2, количество отзывов – 1, со средней оценкой 5.0.
Вы можете запустить рекламную кампанию через сервис Telega.in, выбрав удобный формат размещения. Платформа обеспечивает прозрачные условия сотрудничества и предоставляет детальную аналитику. Стоимость размещения составляет 4055.94 ₽, а за 3 выполненных заявок канал зарекомендовал себя как надежный партнер для рекламы в TG. Размещайте интеграции уже сегодня и привлекайте новых клиентов вместе с Telega.in!
Вы снова сможете добавить каналы в корзину из каталога
Комментарий