简体   繁体   English

C++ 中的“深拷贝”构造函数

[英]A 'deep copy' constructor in C++

I want to build a copy constructor Pair(const Pair& other) .我想构建一个复制构造函数Pair(const Pair& other) This takes as its argument a read-only reference to another Pair .它将对另一个Pair的只读引用作为其参数。 It should set up the newly constructed Pair as a "deep copy".它应该将新构建的Pair设置为“深拷贝”。 But I have no idea on how to set up the integers at these new locations, which should be assigned values according to the integers that the other Pair is pointing to.但我不知道如何在这些新位置设置整数,应该根据另一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;
}

Your converting constructor is not assigning values to the int s it allocates, and it is not assigning those pointers to the class members.您的转换构造函数没有为其分配的int分配值,也没有将这些指针分配给 class 成员。

Your copy constructor is likewise not assigning the allocated pointers to the class members.您的复制构造函数同样没有将分配的指针分配给 class 成员。 It is also not using the * operator correctly when accessing other 's members.访问other成员时,它也没有正确使用*运算符。

Your destructor needs to delete the class members that the constructors allocated.您的析构函数需要delete构造函数分配的 class 成员。

And you need to add a copy assignment operator to finish out the Rule of 3 properly.并且您需要添加一个复制赋值运算符才能正确完成规则 3

Try this:尝试这个:

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

Your first constructor could look like that:您的第一个构造函数可能如下所示:

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

And you don't need to write complex code multiple time by forwarding to the first constructor.而且您不需要通过转发到第一个构造函数来多次编写复杂的代码。

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

Another thing is that you must also implement assignment operator.另一件事是您还必须实现赋值运算符。 Otherwise, your code would be very error prone if you accidently do an assignment (as you would have a double delete assuming that your destructor is properly implemented.否则,如果您不小心进行了赋值,您的代码将非常容易出错(因为假设您的析构函数已正确实现,您将进行双重delete

Having said that, your destructor should be:话虽如此,您的析构函数应该是:

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

As other have said, it would be simpler to directly use int for members as you would not have to define copy and assignment yourself.正如其他人所说,直接将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;
}

If you really need pointers, then I would recommend you to use std::unique_ptr instead.如果您真的需要指针,那么我建议您改用std::unique_ptr

In your class the declaration become std::unique_ptr<int> pa;在您的 class 中,声明变为std::unique_ptr<int> pa; and similar for pb .pb类似。 At that point your destructor become empty.那时你的析构函数变成空的。 Remaining code could stay the same.其余代码可以保持不变。

Also it is preferable to avoid making variable member public and even more in a case like this where you have dynamically allocated memory.此外,最好避免将变量成员public ,甚至在动态分配 memory 的情况下避免公开变量成员。

You can use custom constructor, copy constructor as below:您可以使用自定义构造函数,复制构造函数如下:

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

Your init constructor and copy constructor may have some mistakes.您的 init 构造函数和复制构造函数可能有一些错误。

the init constructor should be: init 构造函数应该是:

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

And copy constructor should be:复制构造函数应该是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM