Нужны delete[] для массивов, public-наследование, виртуальный деструктор Foo и глубокое копирование. Обычное копирование указателей приводит к общему владению одним буфером и двойному удалению.
Найдите и исправьте ошибки в приведённом C++ коде
Нужны delete[] для массивов, public-наследование, виртуальный деструктор Foo и глубокое копирование. Обычное копирование указателей приводит к общему владению одним буфером и двойному удалению.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В этом фрагменте C++ кода есть проблемы, связанные с управлением динамической памятью и наследованием. Не меняя структуру классов, исправьте ошибки, чтобы программа корректно создавала, копировала и удаляла объекты.
class Foo
{
public:
Foo(int size) { i = new int[size]; }
~Foo() { delete i; }
private:
int* i;
};
class Bar : Foo
{
public:
Bar(int size) : Foo(size) { i = new char[size]; }
~Bar() { delete i; }
private:
char* i;
};
void main()
{
Foo* f = new Foo(100);
Foo* b = new Bar(200);
*f = *b;
delete f;
delete b;
}
Ответ
Нужны delete[] для массивов, public-наследование, виртуальный деструктор Foo и глубокое копирование. Обычное копирование указателей приводит к общему владению одним буфером и двойному удалению.
Вариант с сохранением двух классов и их отдельных динамических массивов:
#include <algorithm>
#include <cstddef>
#include <memory>
#include <utility>
class Foo {
std::size_t n;
int* i;
protected:
void swap(Foo& other) noexcept {
std::swap(n, other.n);
std::swap(i, other.i);
}
public:
explicit Foo(std::size_t size) : n(size), i(new int[n]{}) {}
Foo(const Foo& other) : Foo(other.n) {
std::copy_n(other.i, n, i);
}
Foo& operator=(Foo other) {
swap(other);
return *this;
}
virtual ~Foo() { delete[] i; }
};
class Bar : public Foo {
std::size_t n;
char* i;
void swap(Bar& other) noexcept {
Foo::swap(other);
std::swap(n, other.n);
std::swap(i, other.i);
}
public:
explicit Bar(std::size_t size)
: Foo(size), n(size), i(new char[n]{}) {}
Bar(const Bar& other)
: Foo(other), n(other.n), i(new char[n]) {
std::copy_n(other.i, n, i);
}
Bar& operator=(Bar other) {
swap(other);
return *this;
}
~Bar() override { delete[] i; }
};
int main() {
auto f = std::make_unique<Foo>(100);
std::unique_ptr<Foo> b = std::make_unique<Bar>(200);
*f = *b;
}
Размер хранится вместе с массивом; copy-and-swap не теряет прежний буфер, если создание копии не удалось. В main используется стандартная сигнатура int и RAII для самих объектов. *f = *b копирует только часть Foo, поскольку присваивание не полиморфно. Для копирования целого объекта неизвестного производного типа нужен отдельный контракт clone.