包含对其他对象的引用的对象的深层副本

时间:2011-10-17 16:51:05

标签: c++ reference smart-pointers deep-copy

我有一个“sum”类,它包含对现有int的两个引用(比如说)。我想创建一个深度复制整数的“复制”方法。由于智能指针,我以为我永远不会在我的代码中手动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 个答案:

答案 0 :(得分:2)

常量的“深层”副本有什么意义?无论如何,常数都将具有相同的值!所以只需复制(即别名)const-references:

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; }
  // ...
};

如果您担心从具有对局部变量的引用的函数返回副本时悬空引用,则不要使该类具有const引用,而是复制。这样你就可以自然地为你的班级提供你似乎想要的复制语义。

如果你认为你可以根据你的使用方式制作一种非拥有或拥有的混合动力,那么我会说这是你应该避免的糟糕设计。确定您的班级是否拥有数据的所有权,然后随之滚动。

答案 1 :(得分:1)

我认为你混淆了两个不相容的概念。

如果通过引用进行初始化,则应引用其生命周期已定义且应该比对象长的现有对象。

如果您要创建对象的副本,因为指的是某些内容,您的副本也会引用那个的内容。

如果你想拥有自己动态提供的对象,你应该使用指针,并将它们作为指针获取(并在销毁时删除它们)。然后,副本可以深度创建指向对象的副本(或者可以使用引用计数或shared_ptr共享它们)。

你实际上正在混合这两件事,导致可能的问题:想想:

int main()
{
    const int x=5; //whatever it is
    Foo foo(x);
    // ...
} //danger here! ~Foo() will delete x

答案 2 :(得分:0)

引用不会被深度复制,因为它们指向一个对象。因此,您修复的代码应如下所示:

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() {
   }

};