C ++中的“深层复制”构造函数

时间:2019-10-25 00:17:59

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

我想构建一个副本构造器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;
}

4 个答案:

答案 0 :(得分:2)

您的转换构造函数没有为其分配的int分配值,也没有将这些指针分配给类成员。

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

答案 1 :(得分: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<int> pa;,对于pb则类似。届时,您的析构函数将变为空。其余代码可以保持不变。

  

此外,最好避免使用变量成员public,在这种情况下,甚至在动态分配内存的情况下,更是如此。

答案 2 :(得分:0)

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

[('Jack', 90, 190), ('Thomas', 70, 180),('Oliver', 75, 180),('Charlie', 80, 180), ('Jacob', 60, 175), ('Harry', 75, 175)]

答案 3 :(得分:-1)

您的init构造函数和copy构造函数可能会出现一些错误。

init构造函数应为:

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