C + + deep copy and shallow copy

Source: Internet
Author: User

For normal types of objects, replication between them is simple, for example:
int a=88;
int b=a;
Double f=3.12;
Double d (f);

And the class object is different from ordinary object, the internal structure of class object is generally more complex, there are various data members.

#include <iostream>  using namespace std;  class Test  {  private:      int a,b;  public:      Test(int x, int y)     //提供的形式参数,是为了给数据成员直接初始化的      {          a=x;          b=y;      }      Test(const Test& C)   //复制构造函数,提供一个同类型对象作为参数      {          a=C.a;          b=C.b;      }      void show ()      {          cout<<a<<"  "<<b<<endl;      }  };  int main()  {      Test a(100,10);    //执行构造函数Test::Test(int x, int y)      Test b(a);      //执行构造函数Test::Test(const Test& C)      Test c=a;      //也执行构造函数Test::Test(const Test& C)      b.show();      c.show();      return 0;  }    运行程序,屏幕输出两行100   10。
    从以上代码的运行结果可以看出,系统在声明对象b和c时,完成了由对象a的复制。    复制构造函数,就类对象而言,相同类型的类对象是通过复制构造函数来完成整个复制过程的。    上例中的Test::Test(const Test& C),就是我们自定义的复制构造函数。可见,复制构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,用来约束作为参数的对象在构造新对象中是不能被改变的。    当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,复制构造函数就会被自动调用。也就是说,当类的对象需要复制时,复制构造函数将会被调用。以下情况都会调用复制构造函数:

An object passed into the function body as a value
An object is returned from the function in the way that the value is passed
An object needs to be initialized with another object.
If a copy constructor is not explicitly declared in the class, the compiler will automatically generate a default copy constructor that completes a shallow copy between objects, which is explained later.
A custom copy constructor is a good programming style that prevents the compiler from forming a default copy constructor to improve the efficiency of the source code.

Shallow copy and deep copy
The so-called shallow copy, as is handled in the above constructor, directly assigns a value to the data member. In many cases, this is possible. Creates a new object that allocates storage space for the object's data members, and the value is saved in the appropriate space by assigning the value directly. However, this shallow copy, but does not pass the world, the following procedure, shallow copy brings the problem.

#include <iostream>  #include <cstring>  using namespace std;  class Test  {  private:      int a;      char *str;  public:      Test(int b, char *s)      {          a=b;          strcpy(str,s);  //肇事地点,但不是祸端      }      Test(const Test& C)      {          a=C.a;          strcpy(str,C.str);      }      void show ()      {          cout<<a<<","<<str<<endl;      }  };  int main()  {      Test a(100,"hello");      Test b(a);      a.show();      b.show();      return 0;  }  
    程序运行中,会弹出一个窗口:程序的执行意外停止了。面对这个窗口,我们应该有感觉,这和使用指针不当有关系。

We look at the main function.

When the program executes to line 28th, test a ("Hello"), the data member of object A gets the value of the actual parameter 100, and the data member STR, the pointer, is a random address value (the value of the pointer, the value not pointing to the pointer)! In the program, try to pass strcpy (str,s); the string "Hello" that the form parameter s points to is copied to the location pointed to by STR, where the address is not assigned by the system, which is a dangerous operation. Here, Str is such an unassigned address (pointer), known as a "wild pointer".

In the execution of line 29th Test B (a), the same thing will happen.

Str Such a wild pointer is how overbearing! In some systems, such behavior is accepted and can be thought of as how dangerous it is. In some systems, such a thing is not allowed to happen. Therefore, the above program debugging in the Codeblock error. This is a good mistake.

The way to solve this problem is to assign dedicated space to the members of the pointer type in the constructor. The copy built with this rule is called a deep copy!

The above program, rewritten as:

#include <iostream> #include <cstring> using namespace std;      Class Test {Private:int A;  Char *str;          public:test (int b, char *s) {a=b;  Str=new Char[strlen (s) +1]; Allocates the space that Str points to, depending on the string that s points to. For him 1?  The end of the string to use the strcpy (str,s);          The location of the previous procedure, Scourge has been removed from the previous sentence} Test (const test& C) {a=c.a;   Str=new Char[strlen (C.STR) +1];      Ibid, so str is not a wild pointer strcpy (STR,C.STR);      } ~test () {delete []str;      } void Show () {cout<<a<< "," <<str<<endl;  }  };      int main () {Test A (+, "hello");      Test B (a);      A.show ();      B.show ();  return 0; } "Well, the STR members of A and B objects, explicitly assigning space, they are no longer wild pointers. Because space is explicitly allocated, the corresponding space is freed from the destructor.        We can not use the wild pointer, of course, can not object to be revoked, but also occupy space, do not do things like this kind.        The deep copy is represented in the 13th and 19th lines where the allocation pointer is to the space, and the address of the space will also be the value of the pointer (distinguish the value of the pointer from the value pointed to by the pointer). Here is another example where a data member of Class A can save Len Integer data. The data member Arrayaddr in the class is a pointer to an integral type and can be used as the starting address for a unary array. This class has pointers to data members, and in the definition of constructors, it is necessary to use a deep copy method, this is reflected in line 16th. In addition, the release of the allocated space is completed in the destructor

#include <iostream>
using namespace Std;
Class A
{
Private
int arrayaddr;//holds the first address of an array with Len integer elements
int Len; Record the length of a dynamic array
Public
A (int
a, int n);
~a ();
int sum ();
};
a::a (int *a, int n)
{
Len=n;
Arrayaddr=new Int[n]; Allocate space for pointer data members, note that there is no addition to 1 in the above example
for (int i=0; i<n; i++)//individually copy the value of A to
{
Arrayaddr[i]=a[i];
}
}
Out-of-class definition of the destructor, releasing the space pointed to by the pointer data a
A::~a ()
{
delete [] arrayaddr;
}
int a::sum ()//Get the value of the element labeled I in the array A points to
{
int s=0;
for (int i=0; i<len; i++)//individually copy the value of A to
{
S+=arrayaddr[i];
}
return s;
}

int main () {
int b[10]= {75, 99, 90, 93, 38, 15, 5, 7, 52, 4};
A R1 (b,10);
cout<< "and:" <<r1.sum () <<endl;
int c[15] = {18,68,10,52,3,19,12,100,56,96,95,97,1,4,93};
A R2 (c,15);
cout<< "and:" <<r2.sum () <<endl;
return 0;
}

C + + deep copy and shallow copy

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.