class SomeClass
{
public:
SomeClass(T* Pointer, ...)
: _Pointer(Pointer) { }
private:
T* _Pointer;
}
Суть такова: передаем конструктору класса указатель на некоторый объект, он запоминает его и использует в своих целях.
Если мы динамически создали такой объект специально для передачи его в такой конструктор, то неплохо бы, чтобы деструктор этого класса автоматически удалил его из динамической памяти:
class SomeClass
{
public:
SomeClass(T* Pointer, ...)
: _Pointer(Pointer) { }
private:
auto_ptr<T> _Pointer;
}
SomeClass SomeInstance(new T(), ...);
Однако такой вариант предполагает, что мы обязательно будем создавать объекты типа T динамически, и экземпляр класса SomeClass будет владеть ими. Что не позволит:
1. передавать ссылки на объекты, которыми владеет кто-либо другой:
T Array[3];
SomeClass SomeInstance(&Array[2], ...);
2. использовать конструктор копирования и оператор присваивания, генерируемый компилятором по умолчанию (т.к. при копировании auto_ptr "донор" теряет ссылку).
Второй пункт можно обойти заменой auto_ptr на shared_ptr. Тем же самым методом можно обойти и первый пункт, если добавить немного кода:
struct NullDeleter
{
void operator()(const void *p) { /* ничего не делаем */ }
};
class SomeClass
{
public:
SomeClass(shared_ptr<T> Pointer, ...)
: _Pointer(Pointer) { }
private:
shared_ptr<T> _Pointer;
}
// передаем владение
SomeClass SomeInstance(new T(), ...);
// владение не передаем
T Array[3];
SomeClass SomeInstance(shared_ptr<T>(&Array[2], NullDeleter(), ...);
Плюс такого решения еще в том, что можно помимо двух крайностей "владеет"/"не владеет", наш класс получает третью возможность - "совладеет":
vector<shared_ptr<T> > v;
v.insert(new T());
...
SomeClass SomeInstance(v[0], ...);
...
v.clear();
Минус этого решение в том, что shared_ptr имеет много оверхеда (как по использованию памяти, так по процессорному времени) по сравнению с написанием специализированного класса, поддерживающего только два состояния: "владеет"/"не владеет".
Комментариев нет:
Отправить комментарий