Deep Copy with Copy 构造函数

Deep Copy with Copy Constructor

提问人:FooStack 提问时间:7/2/2022 最后编辑:Alan BirtlesFooStack 更新时间:7/2/2022 访问量:916

问:

我有一个任务,我需要执行以下操作。

我有 3 个班级,其中 A 链接到许多 B Picture 关联A->*B->*C

A: Contains only -iA_ : int
B: Contains only -iB_ : int
C: Contains only -IC_ : int

任务是:

为所有类实现必要的代码,以便包含深度副本的复制结构。容器类型列表。二传手和吸气剂不是必需的!A

不需要其他构造函数和析构函数!

如果您使用默认实现,则必须证明这一点。

所以我已经实现了它,这是对的吗?

class C
{
   private:
   int iC_;
}
class B
{
   private:
      int iB_;
      std::list<C*> CList_;
   public:
   B(std::list<C*> CList) : CList_(CList)
   {
   }
}
class A
{
   private:
      int iA_;
      std::list<B*> BList_;
   public:
   A(std::list<B*> BList) : BList_(BList)
  {
  }
  A(const A& crA)
 {
   iA_ = crA.iA_;
 }

}
C++ 复制构造函数 Deep-Copy

评论

1赞 fabian 7/2/2022
不。的“复制构造函数”使列表留空,我看不出不简单地使用或代替使用指针集合的意义:如果您对 做同样的事情,这将允许您使用默认的复制构造函数来制作整个结构的深度副本......() 顺便说一句:您还需要以 结束类定义。Astd::list<B>std::vector<B>Bclass C {int iC_;}; class B {int iB_; std::vector<C> m_cs; }; class A {int iA_; std::vector<B> m_bs; };;
2赞 Goswin von Brederlow 7/2/2022
你真的不应该在那里使用指针。这只能以一种不会以混乱结束的方式读取:列表没有指针的所有权。因此,您不能在列表中深度复制它们,因为这会创建所有权。您需要一些全局实例来注册复制的指针以供以后清理,或者 List 必须有一个处理此问题的分配器。
1赞 Goswin von Brederlow 7/2/2022
如果列表具有指针的所有权,则指针应该是指针的所有权,然后复制构造函数可用于在迭代列表时复制每个对象。(注意:B 也需要一个复制构造函数来使其深入)。但是,没有指针的意义何在?在大多数情况下,更好的方法是,没有复制结构并使用浅拷贝。unique_ptrstd::make_unique(*it)std::shared_ptr
0赞 Eljay 7/2/2022
似乎解决方案可以像 Might replace with 一样简单。据我所知,不需要指针。struct C { int iC_{}; }; struct B { vector<C> links; int iB_{}; }; struct A { vector<B> links; int iA_{}; };vectorlist

答:

0赞 Allie 7/2/2022 #1

很遗憾,您的代码还不正确。若要创建包含指针的类的深层副本,还需要复制这些指针指向的对象。下面是一个只有 A 和 B 的简单示例:

class B
{
 private:
    int iB_;
 public:
    // you will not be able to default this in your code
    B(const B& other) = default;
};

class A
{
 private:
    int iA_;
    vector<B*> BList_;
 public:
    A(const A& other) : iA_{other.iA_}, BList_{}
    {
        // fill up the BList_ with copies of other's BList_ items
        for (auto b : other.BList_) {
            // call B's copy constructor
            B* copyPtr = new B{*b};
            BList_.push_back(copyPtr);
        }
    }

    A& operator=(const A& other)
    {
        iA_ = other.iA_;

        // destroy all the current items in BList_
        while (!BList_.empty()) { delete BList_.pop_back(); }

        // fill up the BList_ with copies of other's BList_ items
        for (auto b : other.BList_) {
            // call B's copy constructor
            B* copyPtr = new B{*b};
            BList_.push_back(copyPtr);
        }
    }

    ~A()
    {
        // destroy all the current items in BList_
        while (!BList_.empty()) { delete BList_.pop_back(); }
    }
};

对于你的代码,你还需要用 B 的复制构造函数实现类似的东西,以确保它复制了 中的所有内容,只有这样你才会有一个真正的深度复制。CList_

编辑:正如 @Alan Birtles 所指出的,在这样的实现中,您还应该定义复制分配运算符和析构函数以防止内存泄漏。

评论

0赞 Alan Birtles 7/2/2022
你应该确保你的代码遵循三法则
0赞 Allie 7/2/2022
@AlanBirtles非常好的观点,刚刚更新了答案,谢谢!