глубокая копия объекта, содержащая ссылки на другие объекты - PullRequest
2 голосов
/ 17 октября 2011

У меня есть класс "sum", который содержит две ссылки на существующие целые числа (скажем).Я хочу создать метод «копирования», который копирует глубины.Я думал, что мне никогда не придется вручную delete объекты в моем коде, благодаря умным указателям, но я должен был в этом решении.Более того, это слишком сложно для такой тривиальной задачи (которую мне нужно повторить для нескольких классов).Есть ли более простое решение?

Примечание: я не хочу добавлять член bool к каждому объекту, чтобы определить, нужно ли удалять целые числа (в моем случае это не лучшие издержки, чем std::set проверочные накладные вдеструктор)

#include <set>

struct sum {
   const int &a, &b;
   static std::set<const int*> allocated_ints;

   sum(const int& a, const int&b): a(a), b(b) {}

   sum copy() const {
       sum res(*new const int(a), *new const int(b));
       allocated_ints.insert(&res.a);
       allocated_ints.insert(&res.b);
       return res;
   }

   ~sum() {
       if (allocated_ints.count(&this->a)) {
           delete &this->a;
           delete &this->b;
           allocated_ints.erase(&this->a);
           allocated_ints.erase(&this->b);
       }
   }

};

std::set<const int*> sum::allocated_ints;

Ответы [ 3 ]

2 голосов
/ 17 октября 2011

Какой смысл "глубокой" копии констант ?Константы будут иметь одинаковое значение, несмотря ни на что!Так что просто скопируйте (то есть псевдоним) const-ссылки:

struct Foo
{
  const int & n;

  Foo(const int & m) : n(m) { }
  Foo(const Foo & rhs) : n(rhs.n) { }

  Foo copy() const { Foo f(*this); /* ... */ return f; }
  // ...
};

Если вы беспокоитесь о висячих ссылках при возврате копии из функции со ссылкой на локальную переменную, то не делайтекласс имеет постоянные ссылки, но копии.Таким образом, вы естественным образом предоставляете своему классу семантику копирования, которая, по-видимому, вам нужна в любом случае.

Если вы думали, что могли бы создать гибрид, который либо не принадлежит, либо становится владельцем в зависимости от того, как вы его используете,тогда я бы сказал, что это плохой дизайн, который вы должны избегать.Решите, есть ли у вашего класса право собственности на данные или нет, а затем переходите к ним.

1 голос
/ 17 октября 2011

Я думаю, что вы смешиваете два несовместимых понятия.

Если вы инициализируете по ссылке, вам следует обратиться к существующему объекту, время жизни которого уже определено и должно быть длиннее, чем ваши объекты.

Если вы хотите создать копию своего объекта, поскольку он ссылается на что-то, ваша копия также будет ссылаться на , что что-то.

Если вы хотите владеть динамически предоставляемыми объектами, вы должны использовать для этого указатели и приобретать их как указатели (и удалять их при уничтожении).Затем копия может глубоко создавать копии указанных объектов (или может делиться ими с помощью подсчета ссылок или shared_ptr).

Фактически вы смешиваете две вещи, что приводит к возможным проблемам:подумайте:

int main()
{
    const int x=5; //whatever it is
    Foo foo(x);
    // ...
} //danger here! ~Foo() will delete x
0 голосов
/ 17 октября 2011

Ссылки не копируются глубоко, потому что они указывают на объект. Поэтому исправленный код должен выглядеть следующим образом:

struct sum {
   const int &a, &b;

   sum(const int& a, const int&b): a(a), b(b) {}

   sum copy() const {
       sum res(a,b);
       return res;
   }

   ~sum() {
   }

};
...