Занимательная задачка: понимание deep copy
Добавлено: 07 ноя 2015, 15:56
Такую задачу я даю на собеседовании.
В некой программе долгое время "жил" следующий код:
Класс CHuge является сторонним классом. Его особенность в том, что в момент создания объекта этого класса выполняется много "тяжёлых" действий, а именно: выделяется много памяти, производятся продолжительные расчёты. Так же он обладает всем необходимым набором конструкторов и операторов для того, чтобы указанный выше код функционировал правильно. Дополнительно следует знать, что вызов метода DoAction сохраняет результаты своей работы во внутренние переменные, так что каждый последующий вызов этого метода будет работать иначе, чем предыдущие вызовы.
Долгое время всех устраивало состояние кода. Но пришёл тот день, когда грамотный автотестер покрыл все возможные варианты тестами и доложил руководству проектом, что даже когда все три условия в коде ложны, программа всё равно долго "висит", выполняя ненужные действия.
Устранить проблему поручили начинающему разработчику. Первое, что ему пришло в голову, это сделать следующие изменения в классе:
Такие изменения были более, чем обоснованы, так как, благодаря им, инициализация экземпляра CHuge была отложена до первого вызова Process, то есть, иными словами, до того, момента, когда экземпляр на самом деле понадобится. Если Process не вызовется ни разу, то у нас получится избежать выполнения длительных операций, которые производятся при инициализации CHuge.
Однако разработчик всё же что-то упустил из виду, так как после компиляции и запуска этого кода ему довелось лицезреть краш приложения.
Вопросы:
1. Почему произошёл краш?
2. Как исправить краш, но при этом добиться необходимой оптимизации?
Напоминаю, что править мы можем только код класса CWorker, так как класс CHuge является сторонним, а функция main находится не в нашей юрисдикции и мы обязаны сохранить ожидаемое поведение нашего класса для людей, которые эту функцию пишут.
В некой программе долгое время "жил" следующий код:
Код: Выделить всё
#include <huge.h>
class CWorker
{
public:
void Process()
{
m_huge.DoAction();
}
private:
CHuge m_huge;
};
void main()
{
CWorker worker1;
if (<SomeCondition1>)
{
worker1.Process();
}
CWorker worker2;
if (<SomeCondition2>)
{
worker2 = worker1;
}
if (<SomeCondition3>)
{
worker1.Process();
worker2.Process();
}
}
Долгое время всех устраивало состояние кода. Но пришёл тот день, когда грамотный автотестер покрыл все возможные варианты тестами и доложил руководству проектом, что даже когда все три условия в коде ложны, программа всё равно долго "висит", выполняя ненужные действия.
Устранить проблему поручили начинающему разработчику. Первое, что ему пришло в голову, это сделать следующие изменения в классе:
Код: Выделить всё
#include <huge.h>
class CWorker
{
public:
CWorker() : m_pHuge(nullptr)
{
}
~CWorker()
{
delete m_pHuge;
}
void Process()
{
if (nullptr == m_pHuge)
{
m_pHuge = new CHuge();
}
m_pHuge->DoAction();
}
private:
CHuge* m_pHuge;
};
Однако разработчик всё же что-то упустил из виду, так как после компиляции и запуска этого кода ему довелось лицезреть краш приложения.
Вопросы:
1. Почему произошёл краш?
2. Как исправить краш, но при этом добиться необходимой оптимизации?
Напоминаю, что править мы можем только код класса CWorker, так как класс CHuge является сторонним, а функция main находится не в нашей юрисдикции и мы обязаны сохранить ожидаемое поведение нашего класса для людей, которые эту функцию пишут.