Copy constructor)

Source: Internet
Author: User
Many C ++ beginners may know what constructor is, but they are still unfamiliar with the copy constructor. For me, there are not many opportunities to use the copy constructor when writing code, but this does not mean that the copy constructor is useless, in fact, the copy constructor can solve some problems that we often ignore. To illustrate the role of the replication constructor, let me first talk about some of the problems we encounter during programming. We should be familiar with functions in C ++, because they are often used. We are also familiar with class objects, because we often write various classes, use various objects. Are we familiar with pointer operations? Well, if you do not know the above three concepts, I think this article is not suitable for you, but it does not affect you. We often use functions to pass a variety of parameters to functions, but put the object (note that the object is not the object pointer or object reference) it should be rare to pass it as a parameter to the function, and the constructor of this object also involves some memory allocation operations. Well, what's the problem? There are three methods to pass a parameter to a function: value transfer, address transfer, and reference transfer. The former is different from the latter in that when values are passed, a copy of the parameters will be generated in the function, the content of this copy is copied from the original parameter in bits. The content of the two copies is the same. When the original parameter is a class object, it will also generate a copy of the object, but pay attention to it here. Generally, constructor execution is triggered when an object is generated, but this is not the case when a copy of the object is generated. In this case, the object's copy constructor is executed. Why? Generally, constructors perform initialization of member attributes. Before an object is passed to a function, some attributes of the object may have been changed, if the constructor of the object is executed when a copy of the object is generated, the property of the object is restored to the original state, which is not what we want. Therefore, when an object copy is generated, the constructor will not be executed, and a default constructor will be executed. When the function is to be returned after execution, the object copy will execute the destructor. If your destructor is empty, no problem will occur, however, the general destructor must complete some cleanup work, such as releasing the memory space pointed to by the pointer. At this time, the problem may occur. If you allocate memory to a pointer variable in the constructor, release the memory space allocated to the pointer in the destructor, so what will happen when the object is passed to the function and the function is returned after the function ends? First, a copy of the object is generated, and the copy also has a pointer, which is directed to the same memory space as the original object. When the function returns, the object's destructor is executed, that is, the memory space pointed to by the pointer in the object copy is released, but this memory space is still useful to the original object, this is a serious error for the program itself. However, the error is not over yet. When the original object is destroyed, the Destructor executes again. It is an unknown operation to release the dynamically allocated memory space of the same system twice, serious errors may occur. The above is what we will encounter. What is the solution to the problem? The first thing we think of is not to pass Parameters by passing values. We can use the data transfer address or reference. Yes, this can indeed avoid the above situation, and it is the best way to transfer the address or reference when allowed, but this is not suitable for all situations, sometimes we do not want some operations in the function to affect the variables outside the function. What should we do? The replication constructor can be used to solve this problem. The copy constructor is executed when an object copy is generated. We can define our own copy constructor. In the copy constructor, we apply for a new memory space to save the content pointed to by the pointer in the constructor. In this way, when executing the destructor of the object copy, the memory space applied for in the copy constructor is released. In addition to passing an object to a function, the above problem exists. In addition, when the function returns an object, a temporary object is generated, the temporary object is similar to the copy of the object. Copy constructor, often referred to as X (X &), is a special constructor called by the compiler to complete components and initialization of other objects based on the same class. Its unique parameter (Object Reference) is immutable (because it is of the const type ). This function is often used to pass and return values of user-defined types during function calls. The copy constructor calls the copy constructor and member functions of the base class. If possible, it will be called in constant mode, and can also be called in a very large way.
In C ++, the following three objects need to be copied. Therefore, the copy constructor is called.
1). An object passes in the function body as a value.
2). An object is returned from the function by passing values.
3) an object needs to be initialized through another object
In the above cases, you need to copy the call of the constructor. If you do not use the copy constructor In the first two cases, a pointer is directed to the deleted memory space. In the third case, the difference between initialization and assignment is the reason for calling the constructor. In fact, the copy constructor is implemented by the common constructor and the assignment operation assignment. There are many references describing the similarities and differences between the copy constructor and the value assignment operator.
Copying a constructor cannot change the object referenced by it. The reason is as follows: when an object transmits a function by passing a value, the copy constructor is automatically called to generate objects in the function. If an object is passed in to its own copy constructor, its copy constructor will be called to copy this object so that it can pass in its own copy constructor, this leads to an infinite loop.
In addition to being implicitly called when an object is passed into a function, the copy constructor is also called when the object is returned by the function. In other words, all you get from the function is a copy of the object. But likewise, the copy constructor is called correctly, so you don't have to worry about it.
If no copy constructor is explicitly declared in the class, the compiler will create a function for you to perform bitwise copy between objects ). This implicit copy constructor simply associates all class members. Many authors will mention this default copy constructor. It is noted that the implicit copy constructor differs from the explicit copy constructor In the joining mode for members. The explicitly declared copy constructor is associated with the default constructor of the instantiated class members unless another constructor is called during class initialization or the constructor list.
Copying constructor is more efficient because it does not need to change the parameter list of constructor when constructing an object. Designing a copy constructor is a good style. Even if it is provided by the compilation system, you can apply for a default copy constructor in the memory. In fact, the default copy constructor can handle many situations. Additional article on copying constructor:

The initialization method for a simple variable is to use a constant or variable to initialize another variable, for example:
Int M = 80;
Int n = m;
We will already use constructors to initialize objects. Can we use one object to initialize another object just like the initialization of simple variables? The answer is yes. The Point class we previously defined is used as an example:
Point pt1 (15, 25 );
Point pt2 = pt1;
The next statement can also be written as follows:
Point pt2 (pt1 );
It uses pt1 to initialize pt2. At this time, the values of each member of pt2 are the same as those of each member of pt1. That is to say, the values of each member of pt1 are copied to the corresponding members of pt2. In this initialization process, a copy constructor is actually called. When we do not explicitly define a replication constructor, the compiler implicitly defines a default replication constructor, which is an inline, Public member and has the following prototype:
Point: Point (const point &);
It can be seen that the difference between a copy constructor and a constructor is that the former is a reference to a point object, and its function is to copy each Member of an object to the corresponding member of another object.
Although not necessary, we can also explicitly define a replication constructor for the point class:
Point: Point (const point & pt)
{
Xval = pt. xval;
Yval = pt. yval;
}
If a class contains pointer members, an error occurs when initializing objects using the default copy constructor. To illustrate the problem, we assume that object A and object B are the same class and there is a pointer member pointing to object C. When object B is used to initialize object A, the default copy constructor copies the values of each member of object B to the corresponding member of object A, but does not copy Object C. That is to say, pointer members in object A and object B point to object C. In fact, we want Object C to be copied to get object Copy D of Object C. Otherwise, when objects A and B are destroyed, they will be released again in the memory zone of Object C, leading to errors. In order for Object C to be copied, the replication constructor must be explicitly defined. The following uses the string class as an example to describe how to define the replication constructor.

Example 10-11
  Class string
{
Public:
String (); // Constructor
String (const string & S); // copy the constructor
~ String (); // destructor

// Interface function
Void set (char const * data );
Char const * Get (void );

PRIVATE:
Char * STR; // The data member PTR points to the allocated string
};

String: string (const string & S)
{
STR = new char [strlen (S. Str) + 1];
Strcpy (STR, S. Str );
}

We also use an anonymous object to initialize another object, for example:
Point Pt = point (10, 20 );
The class name directly calls the constructor to generate an unknown object. In the above example, use the unknown object on the left to initialize the PT object on the right.
Constructor calls usually occur in the following three situations: the first case is what we see above: when one object is used to initialize another object; the second case is when the object is used as a function parameter, when passing real parameters to the form parameter, the third case is when other temporary objects are created while the program is running. Let's take another example to illustrate the second and third cases:
Point Foo (point pt)
{
...
Return pt;
}
Void main ()
{
Point pt1 = point (10, 20 );
Point pt2;
...
Pt2 = Foo (PT );
...
}
When calling the foo function in the main function, the real parameter PT is passed to the form parameter PT, and the real parameter PT is copied to the form parameter pt. The copy constructor must be called. When the function Foo returns, to create a temporary PT object, you must also call the copy constructor.

Default copy constructor
In the class definition, if no explicit replication constructor is defined, the C ++ compiler automatically defines a default replication constructor. The following is an example of using a copy constructor:

Example 10-12
  # Include <iostream. h>
# Include <string. h>
Class withcc
{
Public:
Withcc (){}
Withcc (const withcc &)
{
Cout <"withcc (withcc &)" <Endl;
}
};

Class wocc
{
Enum {bsz = 100 };
Char Buf [bsz];
Public:
Wocc (const char * MSG = 0)
{
Memset (BUF, 0, bsz );
If (MSG) strncpy (BUF, MSG, bsz );
}
Void print (const char * MSG = 0) const
{
If (MSG) cout <MSG <":";
Cout <Buf <Endl;
}
};

Class Composite
{
Withcc;
Wocc;
Public:
Composite (): wocc ("Composite ()"){}
Void print (const char * MSG = 0)
{
Wocc. Print (MSG );
}
};

Void main ()
{
Composite C;
C. Print ("Contents of C ");
Cout <"calling composite copy-constructor" <Endl;
Composite C2 = C;
C2.print ("Contents of C2 ");
}

A replication constructor is provided for class with2. neither wocc nor composite class explicitly defines the replication constructor. If no explicit replication constructor is defined in the class, the compiler automatically creates a default constructor. However, in this case, this constructor does nothing.
The class composite contains both Member objects of the withcc class and member objects of the wocc class, it uses a non-argument constructor to create the withcc Class Object withoma (note the embedded object wocc initialization method ).
In the main () function, the statement is:
Composite C2 = C;
Object C2 is initialized through object C, and the default replication constructor is called.
The best way is to create your own copy constructor instead of expecting the compiler to create it so that the program is under our own control.

 

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.