Дан фрагмент C++: class A { public: A() {ptr = new int;} ~A() {delete ptr;} A(const A& other) = default; private: int* ptr; }; Объясните проблему и предложите корректные варианты управления ресурсами

9 Дек 2025 в 05:36
19 +1
0
Ответы
1
Проблема. По умолчанию конструктор копирования выполняет поверхностное копирование указателя `ptr`. После копирования два объекта содержат один и тот же адрес, и при разрушении сначала одного, а затем другого произойдёт двойное `delete` (или обращение к уже освобождённой памяти) — UB.
Варианты корректного управления ресурсом (коротко, с примерами).
1) Глубокое копирование (rule of three):
```
class A {
public:
A() : ptr(new int(0)) {}
~A() { delete ptr; }
A(const A& other) : ptr(new int(*other.ptr)) {} // глубокая копия
A& operator=(const A& other) { // копирующее присваивание (copy-and-swap)
if (this == &other) return *this;
int* tmp = new int(*other.ptr);
delete ptr;
ptr = tmp;
return *this;
}
private:
int* ptr;
};
```
2) Реализовать семантику перемещения (move) — перенос владения:
```
class A {
public:
A() : ptr(new int(0)) {}
~A() { delete ptr; }
A(A&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
A& operator=(A&& other) noexcept {
if (this != &other) {
delete ptr;
ptr = other.ptr;
other.ptr = nullptr;
}
return *this;
}
A(const A&) = delete;
A& operator=(const A&) = delete;
private:
int* ptr;
};
```
3) Использовать умные указатели (рекомендуется):
- Для уникального владения — `std::unique_ptr` (копирование запрещено, перенос разрешён):
```
#include
class A {
std::unique_ptr ptr;
public:
A() : ptr(std::make_unique(0)) {}
// деструктор, move ctor/assign по умолчанию корректны; копирование запрещено
};
```
- Для совместного владения — `std::shared_ptr` (копирование безопасно, счётчик ссылок):
```
#include
class A {
std::shared_ptr ptr;
public:
A() : ptr(std::make_shared(0)) {}
// копирование и перемещение по умолчанию корректны
};
```
4) Если динамическая выделение не нужно — хранить `int` напрямую:
```
class A {
int value;
public:
A() : value(0) {}
// все операции копирования/перемещения корректны по умолчанию
};
```
Вывод: не оставляйте “сырые” указатели без явной политики владения. Самый простой и безопасный путь — заменить `int*` на `std::unique_ptr` или `std::shared_ptr`, либо реализовать корректное глубокое копирование/перемещение.
9 Дек 2025 в 06:29
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир