如何在c++中进行深度复制

How do I do a deep copy in c++

本文关键字:深度 复制 c++      更新时间:2023-10-16

我正在尝试对类B进行深度复制,但没有设置a。

为什么b3->print返回垃圾编号而不是1

据我所知,b2和b3都指向同一个A对象。但是我用B的复制构造函数在堆上创建了一个新对象。那么,为什么它们仍然指向同一个对象呢?

我希望这是有道理的。

#include <cstdlib>
#include <iostream>
using namespace std;
class A{
      int num;
public:
       A(int n):num(n){ cout<< "A "<< num << " constructor" <<endl;}  
       ~A(){ cout<< "A "<< num <<" destructor. " <<endl; }   
       int print(){
        cout<< num<< endl;
       }
};
class B{
      A *a;
      int num;
public:
       B(int n):num(n){
           a = new A(n);
           cout<< "B "<< num <<" constructor" <<endl;    
       }  
       ~B(){
            delete a; 
            cout<< "B "<< num <<" destructor"<<endl; 
       }    
       // Copy contructor
       B(const B & b): a(new A(b.num)){ 
       } 
       <strike>int<strike> void print(){
        cout<< num << endl;
       }
       int get_num(){
           return num;
       }
};
int main(int argc, char *argv[])
{ 
    B *b2 = new B(1);
    B *b3(b2);
    b2->print();
    delete b2;
    b3->print();
    system("PAUSE");
    return EXIT_SUCCESS;
}

B *b3(b2);不会按照您的想法行事。

它相当于B* b3 = b2。指针将指向相同的位置。当您执行delete b2;时,您还释放了b3所指向的内存。

要进行深度复制,请执行:

 B* b3 = new B(*b2);

这里还有未定义的行为:

int print(){
   cout<< num << endl;
}

因为你再也回不来了。将返回类型更改为void

要获得预期值:

B(const B & b): a(new A(b.num)), num(b.num){ 
} 

这个问题的其他答案将解释指针是如何工作的,但您也应该明白,不使用指针是更好的解决方案。C++的默认行为与值语义配合得很好。如果按值保存对象,则默认的复制操作符和赋值操作符将执行"深度复制"。

class B{
    A a;
    int num;
public:
    B(int n): a(n), num(n){
        cout<< "B "<< num <<" constructor" <<endl;    
    }    
    void print(){
        cout<< num << endl;
    }
    int get_num(){
        return num;
    }
};

此外,如果你确实使用拥有指针,你通常应该使用智能指针。

这里您不是在复制b2

B *b3(b2);

相反,你正在使b3指向b2

你应该有

B *b3 = new B(*b2);

我想你可能打算写这样的东西:

#include <iostream>
class A
{
public:
    A(int n) : num_(n) {}
    void print() { std::cout << num() << std::endl; }
    int num() const { return num_; }
private:
    int num_;
};
class B
{
public:
    B(int n) : a(n) {}
    int num() const { return a.num(); }
private:
    A a;
};
int main()
{
    B b(1);
    B b2 = b; // deep copy
}

正如你所看到的:

  1. B没有自己的num_成员。应避免重复
  2. 不需要实现复制构造函数或赋值运算符(三条规则)
  3. 此处不需要使用new

在c++中没有浅/深复制这样的东西。您有被复制的值或指针/引用,它们完全定义了复制操作的语义。