C ++ Primer study note _ 19 _ class and data abstraction (5) _ initialization list (const and reference member), copy constructor, primer_19

Source: Internet
Author: User

C ++ Primer study note _ 19 _ class and data abstraction (5) _ initialization list (const and reference member), copy constructor, primer_19

C ++ Primer study note _ 19 _ class and data abstraction (5) _ initialization list (const and reference member), copy constructor

In terms of concept, constructor can be considered to be executed in two phases:

1) initialization phase;

2) Common computing stage. The computing phase consists of all the statements in the constructor body.


I. constructor initialization list

We recommend that you initialize the constructor in the initialization list.

1. Object members and their initialization

#include <iostream>using namespace std;class Object{public:    Object(int num) : num_(num)    {        cout << "Object " << num_ << " ..." << endl;    }    ~Object()    {        cout << "~Object " << num_ << " ..." << endl;    }private:    int num_;};class Container{public:    Container(int obj1 = 0, int obj2 = 0) : obj2_(obj2), obj1_(obj1)    {        cout << "Container ..." << endl;    }    ~Container()    {        cout << "~Container ..." << endl;    }private:    Object obj1_;    Object obj2_;};int main(void){    Container c(10, 20);    return 0;}

Running result:

Object 10...

Object 20...

Container...

~ Container...

~ Object 20...

~ Object 10...

Explanation: the output shows several points. First, the object members must be constructed before the object is constructed. Second, the order of object member construction is related to the order of definition, it has nothing to do with the initialization list order; 3. The construction order is the opposite to the Destructor order; 4. If the class corresponding to the object member does not have the default constructor, the object members can only be initialized in the initialization column table. If the class is inherited and the base class does not have a default constructor, the base class constructor must be called in the initialization list of the derived class constructor.


Example:

Run the following C ++ code. What is the output result?

class A{private:    int i;    int j;public:    A() : j(0), i(j+2) {}    void print() {        cout << "i:" << i << ", j:" << j << endl;    }};int main(){    A a;    a.print();    return 0;}

A: I is the garbage value in the memory, and j is 0. In C ++, the initialization sequence of member variables is the same as that of the variables declared in the type, but it is irrelevant to the order of their initialization list in the constructor.


2. const member and reference member Initialization

-- Const member initialization can only be performed in the const initialization list.
-- The initialization of referenced members can only be performed in the constructor initialization list.
-- Initialize an object member (the class corresponding to the object member does not have the default constructor). It can only be performed in the constructor initialization list.

# Include <iostream> using namespace std; // const member initialization can only be performed in the constructor initialization list // The referenced member initialization can only be performed in the constructor initialization list // object member (the class corresponding to the object Member) no default constructor) class Object {public: enum E_TYPE {TYPE_A = 100, TYPE_ B = 200}; public: Object (int num = 0 ): num _ (num), kNum _ (num), refNum _ (num _) {cout <"Object" <num _ <"... "<endl ;}~ Object () {cout <"~ Object "<num _ <"... "<endl;} void DisplayKNum () {cout <" kNum = "<kNum _ <endl;} private: int num _; const int kNum _; int & refNum _ ;}; int main (void) {Object obj1 (10); Object obj2 (20); obj1.DisplayKNum (); obj2.DisplayKNum (); cout <obj1.TYPE _ A <endl; cout <obj2.TYPE _ A <endl; cout <Object: TYPE_A <endl; return 0 ;}

Running result:

Object 10...

Object 20...

KNum = 10

KNum = 20

100

100

100

~ Object 20...

~ Object 10...


Explanation: Because the const variable or reference must be initialized during definition, the const member and reference member must be initialized in the initialization list. In addition, you can use the defined enumerated type to obtain constants in the class scope.



Ii. copy constructor

-- Only a single parameter, and this parameter is a reference to this type of object (commonly used for const modification), such a constructor is called a copy constructor. Like the default constructor, the copy constructor can be implicitly called by the compiler.

-- Replication constructor, value assignment operator, and destructor are generally referred to as replication control.

-- If a class requires destructor, it also requires the value assignment operator and the copy constructor. This is a useful empirical rule, which is often referred to as the three rule.


1. Two types of replication Constructor

(1) class type Initialization

String book1 ("9-999-99"); // directly initialize the data without calling the copy constructor string book2 = book1; // copy and initialize string book3 (book1 ); // copy initialization string book4 = "9-999-99"; // copy Initialization

(2) When the form parameter or return value is of the class type, the copy constructor replicates the data.

include <iostream>using namespace std;class Myclass{public:        Myclass(int n) { number = n;}        Myclass(const Myclass &other)        {                number = other.number;                cout << "a ";        }private:        int number;};void fun(Myclass p){        Myclass temp(p);}int main(){        Myclass obj1(10), obj2(0);        Myclass obj3(obj1);        fun(obj3);        return 0;}
Running result:

A

Explanation: the three-step copy constructor is called. The first time Myclass obj3 (obj1) in main is used, the second time is the real parameter obj3 to the fun parameter p. The third time is the Myclass temp (p) in function fun) statement.


2. copy constructor -- called when the parameters and return values are not referenced

Function: uses an existing object to initialize a new object of the same type.
Declaration: there is only one parameter and the parameter is a reference to the Class Object Test: Test (const Test & other );
If no replication constructor is defined in the class, the system automatically generates a default replication constructor. As a public member of the class, the system also performs simple member replication.

# Include <iostream> using namespace std; class Test {public: // if the class does not provide any constructor, the system will provide us with a default constructor Test (); explicit Test (int num); Test (const Test & other); void Display () without parameters (); test & operator = (const Test & other );~ Test (); private: int num _;}; // a constructor without parameters is called the default constructor Test: Test (): num _ (0) {cout <"Initializing Default" <endl;} Test: Test (int num): num _ (num) {cout <"Initializing" <num _ <endl;} Test: Test (const Test & other): num _ (other. num _) {cout <"Initializing with other" <num _ <endl;} Test ::~ Test () {cout <"Destroy" <num _ <endl;} void Test: Display () {cout <"num =" <num _ <endl;} Test & Test: operator = (const Test & other) {cout <"Test :: operator = "<endl; if (this = & other) return * this; num _ = other. num _; return * this;} int main (void) {Test t (10); // Test t2 (t); // call the copy constructor Test t2 = t; // equivalent to Test t2 (t); cout <"......... "<endl; return 0 ;}

Running result:

Initializing 10
Initializing with other 10
.........
Destroy 10
Destroy 10

Explanation: The copy constructor is called. The two destroy parameters are t and t2, respectively.


3. Copying constructor calls

When the parameter is not of the reference class type, the value of the real parameter will be copied. Similarly, when the return value is of the non-reference class type, a copy of the median value in the return statement will be returned.

When the function parameter is a class object, it is used to call the function and participate in the combination of real parameters. Create a local object in the memory and copy the real parameters to the new object. The copy constructor is also called. Another point is, why do the parameters of the copy constructor need to be referenced? This is because if the parameter in the copy constructor is not a reference, such as CClass (const CClass c_class), it is equivalent to passing the value (pass-by-value ), the copy constructor of this class is called by passing values, resulting in infinite recursion.


When the return value of a function is a class object, it is used to return the caller after the function is executed. It is also necessary to create a temporary object and then return to the caller. Why not use the partial object to be returned directly?

Because a local object disappears when it leaves the function that creates it, and it cannot survive after the function is called. In this case, the compilation system creates an unknown temporary object in the expression that calls the function. The life cycle of the temporary object is only in the expression at the function call. The so-called return object actually calls the copy constructor to merge the value of this object into a temporary object. If a variable is returned, the process is similar, but the constructor is not called.

# Include <iostream> using namespace std; class Test {public: // if the class does not provide any constructor, the system will provide us with a default constructor Test (); explicit Test (int num); Test (const Test & other );~ Test (); private: int num _;}; // a constructor without parameters is called the default constructor Test: Test (): num _ (0) {cout <"Initializing Default" <endl;} Test: Test (int num): num _ (num) {cout <"Initializing" <num _ <endl;} Test: Test (const Test & other): num _ (other. num _) {cout <"Initializing with other" <num _ <endl;} Test ::~ Test () {cout <"Destroy" <num _ <endl;} void TestFun (const Test t1) {} void TestFun2 (const Test & t1) {} Test TestFun3 (const Test & t1) {return t1;} const Test & TestFun4 (const Test & t1) {// return const_cast <Test &> (t1 ); return t1;} int main (void) {Test t (10); TestFun (t); cout <"........ "<endl; return 0 ;}

(1) running result:

Initializing 10

Initializing with other 10

Destroy 10

.........

Destroy 10

Explanation: The copy constructor is called when the parameter is passed. When the function returns, t 1 of TestFun has reached the survival time, t1 is destroyed before the split line output, and t is destroy.


(2) Replace TestFun (t) with TestFun2 (t );

Running result:

Initializing 10
.........
Destroy 10

Explanation: the parameter is a reference, that is, the copy constructor is not called.


(3) Replace TestFun (t) with t = TestFun3 (t );

Running result:

Initializing 10
Initializing with other 10
Test: operator =
Destroy 10
.........
Destroy 10

Explanation: In the order from right to left, when the function returns, it calls the copy constructor, then calls the value assignment operator, releases the temporary object, and finally releases t. If t is not received, operator = is not called and the temporary object is released immediately.


(4) replace TestFun (t) with Test t2 = TestFun3 (t );

Running result:

Initializing 10
Initializing with other 10
.........
Destroy 10
Destroy 10

Explanation: If the function returns a call to the copy constructor, but does not call the copy constructor again, and the temporary object is not released, it can be understood that the temporary object is changed to T2.


(5) replace TestFun (t); with const Test & t2 = TestFun3 (t );

Running result:

Initializing 10
Initializing with other 10
.........
Destroy 10
Destroy 10

Explanation: When the function returns, the copy constructor is called. Because t2 references a temporary object, it is not released immediately.


(6) replace TestFun (t) with Test t2 = TestFun4 (t );

Running result:

Initializing 10
Initializing with other 10
.........
Destroy 10
Destroy 10

Explanation: The copy constructor is not called when parameters and responses are passed by the function. during initialization of t2, the copy constructor is called.


(7) replace TestFun (t); with const Test & t2 = TestFun4 (t );

Running result:

Initializing 10
.........
Destroy 10

Explanation: No constructor is called for passing parameters and returning results of a function. If t2 is a reference, no copy constructor is called.


4. Comprehensive Practice of destructor and replica Functions
[Example 1]

# Include <iostream> using namespace std; class A {public: A () {cout <"";}~ A () {cout <"~ A ";}}; class B {public: B (A & a): _ a (a) // _ a () the copy constructor {cout <"B" ;}~ is called ";}~ B () {cout <"~ B ";} private: A _ a;}; int main () {A a; // when you define an object, the constructor is automatically called, output a B B B (a); // call the copy constructor return 0 before output B;} // when the declaration cycle of the defined object ends, the system automatically calls the Destructor for release, which is executed in reverse order of the constructor.

Running result:

AB ~ B ~ A ~ A


[Example 2]

# Include <iostream> using namespace std; class A {public: A () {cout <"";}~ A () {cout <"~ A ";}}; class B: public A // B inherits class A {public: B (A & a): _ a (a) using A public Method) // _ a (a) calls the copy constructor {cout <"B ";}~ B () {cout <"~ B ";} private: A _ a;}; int main () {A a; // when you define an object, the constructor is automatically called, output a B B B (a); // call the copy constructor return 0 before output B;} // when the declaration cycle of the defined object ends, the system automatically calls the Destructor for release, which is executed in reverse order of the constructor.

Running result:

AAB ~ B ~ A ~ A ~ A.

Explanation: first, Statement 1 constructs an object A and Outputs. Then Statement 2 calls the constructor of its parent class, Outputs A, and then executes the constructor of B as above.


Refer:

C ++ primer version 4
Valid tive C ++ 3rd

Http://blog.csdn.net/jnu_simba/article/details/9173151

Http://blog.csdn.net/zjf280441589/article/details/24862135
C ++ programming specifications

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Related Article

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.