【问题标题】:A 'deep copy' constructor in C++C++ 中的“深拷贝”构造函数
【发布时间】:2019-10-25 00:17:59
【问题描述】:

我想构建一个复制构造函数Pair(const Pair& other)。它的参数是对另一个Pair 的只读引用。它应该将新构建的Pair 设置为“深拷贝”。但是我不知道如何在这些新位置设置整数,应该根据另一个Pair指向的整数来分配值。

class Pair {
public:
  int *pa,*pb;
  Pair(int a, int b);
  Pair(const Pair & other);
  ~Pair();
};

Pair::Pair(int a, int b){
  pa = new int;
  pb = new int;
  *pa = a;
  *pb = b;
}

Pair::Pair(const Pair & other){
  pa = new int;
  pb = new int;
  *pa = *(other.pa);
  *pb = *(other.pb);
}

Pair::~Pair(){
  delete pa;
  delete pb;
}

int main() {
  Pair p(15,16);
  Pair q(p);
  Pair *hp = new Pair(23,42);
  delete hp;

  std::cout << "If this message is printed,"
    << " at least the program hasn't crashed yet!\n"
    << "But you may want to print other diagnostic messages too." << std::endl;
  return 0;
}

【问题讨论】:

  • 你让它变得比它需要的复杂得多。类中的 A 和 B 成员应该是 int 而不是指向 int 的指针,并且您不需要专门 malloc 那些。此外,假设您在构造函数中时已经分配了对象,只需将传入的值复制到您的成员变量中。
  • int *pa = new int; 在你的两个构造函数中,与类成员 pa 无关。你的意思是pa = new int;?另外,a = *pa; 是倒退的,你是说*pa = a; 吗? pb 也是如此。除此之外:您正在泄漏内存,因为您从未delete 它。考虑向good C++ book学习。
  • @RussSchultz 如果将这些变量设为ints,而不是指向ints 的指针 - 用户定义的复制构造函数没有任何作用,因为编译器生成的复制构造函数可以满足人们的所有需求.
  • @Algirdas Preidžius 对于“指向 int 的指针”,它们旨在指向存储整数的堆内存位置。
  • @robinzx117 你已经有了一个拷贝构造函数。为什么你认为它没有做你想做的事?

标签: c++ pointers constructor copy-constructor deep-copy


【解决方案1】:

您的第一个构造函数可能如下所示:

Pair::Pair(int a, int b)
    : pa(new int(a))
    , pb(new int(b))
{
}

而且你不需要通过转发到第一个构造函数来多次编写复杂的代码。

Pair::Pair(const Pair & other) 
    : Pair(*other.pa, *other.pb) 
{
}

另一件事是您还必须实现赋值运算符。否则,如果您不小心进行了赋值,您的代码将非常容易出错(因为假设您的析构函数已正确实现,您将有一个双重 delete

话虽如此,你的析构函数应该是:

Pair::~Pair()
{
    delete pa;
    delete pb;
}

正如其他人所说,直接将int 用于成员会更简单,因为您不必自己定义副本和分配。

// Inside class declaration
Pair &operator=(const Pair &other);

// With other definitions.
Pair &Pair::operator=(const Pair &other)
{
    *pa = *other.pa;
    *pb = *other.pb;
    return *this;
}

如果你真的需要指针,那么我建议你改用std::unique_ptr

在您的班级中,声明变为std::unique_ptr&lt;int&gt; pa;pb 类似。那时你的析构函数变成空的。其余代码可以保持不变。

此外,最好避免创建变量成员public,在动态分配内存的情况下甚至更多。

【讨论】:

  • 您忘记在赋值运算符中使用return *this;
  • @PaulMcKenzie 已修复。
  • 在赋值运算符中,other.pa 必须是 *other.papb 相同
  • 通过添加 * 修复
【解决方案2】:

您的 converting 构造函数没有将值分配给它分配的ints,也没有将这些指针分配给类成员。

您的 copy 构造函数同样没有将分配的指针分配给类成员。在访问other 的成员时,它也没有正确使用* 运算符。

你的析构函数需要delete构造函数分配的类成员。

您需要添加一个复制赋值运算符来正确完成Rule of 3

试试这个:

class Pair {
public:
  int *pa,*pb;
  Pair(int a, int b);
  Pair(const Pair & other);
  ~Pair();
  Pair& operator=(const Pair & other);
};

Pair::Pair(int a, int b){
  pa = new int;
  pb = new int;
  *pa = a;
  *pb = b;

  /* alternatively:
  pa = new int(a);
  pb = new int(b);
  */
}

Pair::Pair(const Pair & other){
  pa = new int;
  pb = new int;
  *pa = *(other.pa);
  *pb = *(other.pb);

  /* alternatively:
  pa = new int(*(other.pa));
  pb = new int(*(other.pb));
  */
}

Pair::~Pair(){
  delete pa;
  delete pb;
}

Pair& Pair::operator=(const Pair & other){
  *pa = *(other.pa);
  *pb = *(other.pb);
  return *this;
}

int main() {
  Pair p(15,16);
  Pair q(p);
  Pair *hp = new Pair(23,42);
  p = *hp;
  delete hp;

  std::cout << "If this message is printed,"
    << " at least the program hasn't crashed yet!\n"
    << "But you may want to print other diagnostic messages too." << std::endl;
  return 0;
}

【讨论】:

  • 对于赋值运算符,如果使用swap 成语,则无需验证自赋值(实践中很少发生)。在这种情况下,交换习语并不合适,因为它会使代码更加复杂。 Ans 如果你想使用swap 成语,那么为Pair 对象定义交换函数是有意义的。
【解决方案3】:

您可以使用自定义构造函数,复制构造函数如下:

 class Pair {
 public:
   int *pa,*pb;
   Pair(int, int);
   Pair(const Pair &);
  ~Pair();
 };

 /*
 * Implement its member functions below.
 */
 Pair::Pair(int a, int b){
  pa = new int;
  pb = new int;
  *pa = a;
  *pb = b;
}

Pair::Pair(const Pair & other){
  pa = new int;
  pb = new int;
  *pa = *(other.pa);
  *pb = *(other.pb);
}

Pair::~Pair(){
  delete pa;
  delete pb;
}

 /* Here is a main() function you can use
  * to check your implementation of the
  * class Pair member functions.
  */

int main() {
  Pair p(15,16);
  Pair q(p);
  Pair *hp = new Pair(23,42);
  delete hp;

  std::cout << "If this message is printed,"
    << " at least the program hasn't crashed yet!\n"
    << "But you may want to print other diagnostic messages too." << std::endl;
  return 0;
}

【讨论】:

    【解决方案4】:

    你的初始化构造函数和拷贝构造函数可能有一些错误。

    初始化构造函数应该是:

    Pair::Pair(int a, int b){
      pa = new int;
      pb = new int;
      *pa = a;
      *pb = b;
    }
    

    而拷贝构造函数应该是:

    Pair::Pair(const Pair & other){
      pa = new int;
      pb = new int;
      *pa = *(other.pa);
      *pb = *(other.pb);
    }
    

    【讨论】:

    • 您在 2 上修复了 1 个重大错误,大约半小时后它们在评论中被指出...
    猜你喜欢
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    相关资源
    最近更新 更多