Object initialization in C ++

Source: Internet
Author: User

Object initialization in C ++
The constructor initializes the C ++ object during creation. For a single class without an inheritance relationship, apart from the generation and designation of the constructor itself, the initialization steps and the initialization methods of the members are also involved. This note mainly introduces these details, find out some basic running rules of the C ++ object during initialization.Specify the constructorWhen designing a class, we usually write the corresponding default constructor, copy constructor, copy assignment operator, and deconstructor for this class. Even if we write only one empty class, the compiler will still declare a default constructor, copy constructor, copy assignment operator and deconstructor for it during compilation, if they exist in the Code, the compiler will create them at this time.

1 class MyCppClass2 {                                                                                                                                    3 }

 

Once we write the default constructor for a class, the compiler will not generate the default constructor for it by default. The same applies to several other functions. For the constructor generated by the compiler by default, it initializes each data member according to certain rules. Considering the importance of member initialization, you need to be rigorous when writing your own constructor. This is especially important in the case of class derivation and inheritance. For the use cases of copy constructor and assignment operator, I have to say a little more here. See the following code:

 1 #include <iostream> 2   3 using std::cout; 4 using std::endl; 5   6 class MyCppClass 7 { 8 public: 9     MyCppClass()10     {11         std::cout <<"In Default Constructor!" <<std::endl;12     }13  14     MyCppClass(const MyCppClass& rhs)15     {16         std::cout <<"In Copy Constructor!" <<std::endl;17     }18  19     MyCppClass& operator= (const MyCppClass& rhs)20     {21         std::cout <<"In Copy Assignment Operator!" <<std::endl;22  23         return *this;24     }25 };26  27 int main()28 {29     MyCppClass testClass1;                 // default constructor30     MyCppClass testClass2(testClass1);     // copy constructor31     testClass1 = testClass2;               // copy assignment operator32  33     MyCppClass testClass3 = testClass1;    // copy constructor34  35     return 0;36 }


Execution result:

Note that, in general, we always think that the '=' operator calls the copy assignment operator, which is an exception. That is, when a new object is defined, even if the '=' operator is used, it actually calls the initialization function copy constructor, instead of calling copy assignment operator to assign values. Why initialization listAn object is initialized in two steps: first, allocate memory to save the object, and then execute the constructor. When executing the constructor, if there is an initialization list, execute the initialization list first, and then execute the constructor's function body. So Why will the initialization list be introduced? Compared with C, C ++ in program organization changes from "process-oriented with function as the basic unit" to "Class-oriented object-oriented ", classes also serve as a composite data type, and the initialization list is nothing more than data initialization. Here, we can naturally infer that the initialization list is associated with the initialization of data types such as classes. After the initialization list is introduced, there are two methods for initializing the data members of a class. The following is a comparison between the built-in and custom data member types of the class.
1 // data member type is built-in type 2 class MyCppClass 3 {4 public: 5 // value assignment operation for member initialization 6 MyCppClass 7 {8 counter = 0; 9} 10 11 // initialize the list of members 12 MyCppClass: counter (0) 13 {14} 15 16 private: 17 int counter; 18}

 

When the data member type of the class is a built-in type, the above two initialization methods have the same effect. When the data member type is also a class, the initialization process will be different, for example:
1 // data member type is custom type: A class 2 class MyCppClass 3 {4 public: 5 // value assignment operation for member initialization 6 MyCppClass (string name) 7 {8 counter = 0; 9 theName = name; 10} 11 12 // initialize the list of Members 13 MyCppClass: counter (0), theName (name) 14 {15} 16 17 private: 18 int counter; 19 string theName; 20}

 

In the theName = name statement in the constructor body, theName first calls the default constructor of string for initialization, and then calls the copy assignment opertor to copy and assign values. For the initialization list, the copy constructor is used for initialization. Obviously, you can use the following code for testing.
 1   2 #include <iostream> 3 #include <string> 4   5 class SubClass 6 { 7 public: 8     SubClass() 9     {10         std::cout <<" In SubClass Default Constructor!" <<std::endl;11     }12  13     SubClass(const SubClass& rhs)14     {15         std::cout <<" In SubClass Copy Constructor!" <<std::endl;16     }17  18     SubClass& operator= (const SubClass& rhs)19     {20         std::cout <<" In SubClass Copy Assignment Operator!" <<std::endl;21  22         return *this;23     }24 };25  26 class BaseClass27 {28 public:29     BaseClass(const SubClass &rhs)30     {31         counter = 0;32         theBrother = rhs;33         std::cout <<" In BaseClass Default Constructor!" <<std::endl;34     }35  36     BaseClass(const SubClass &rhs, int cnt):theBrother(rhs),counter(cnt)37     {38         std::cout <<" In BaseClass Default Constructor!" <<std::endl;39     }40  41     BaseClass(const BaseClass& rhs)42     {43         std::cout <<" In BaseClass Copy Constructor!" <<std::endl;44     }45  46     BaseClass& operator= (const BaseClass& rhs)47     {48         std::cout <<" In BaseClass Copy Assignment Operator!" <<std::endl;49  50         return *this;51     }52 private:53     int counter;54     SubClass theBrother;55 };56  57 int main()58 {59     SubClass subClass;60  61     std::cout <<"\nNo Member Initialization List: " <<std::endl;62     BaseClass BaseClass1(SubClass);63  64     std::cout <<"\nMember Initialization List: " <<std::endl;65     BaseClass BaseClass2(SubClass, 1);66  67     return 0;68 }

Execution result:

That is, when custom type Initialization is involved, using the initialization list to complete initialization will be more efficient. This is also a highlight of the initialization list. Even for built-in types, you need to use the initialization list in some cases to complete initialization, such as the const and references member variables. Here is a note that describes the initialization list in detail. Several initialization termsWhen I read the Chinese version of Accelerated C ++, I always encounter "Default initialization", "implicit initialization", and "numerical initialization". At first, I took several twists and turns to understand these terms, I always think that an initialization operation has created so many nouns that it does not take much time to figure out the relationship between them.
To better understand them, we need to divide the data types in C ++ first. In C ++, data types can be roughly divided into two types: the first is the built-in type, such as float, int, double, and so on; the second is the custom type, that is, the class we commonly use, defined by struct. When initializing these types of data, the difference is shown: For built-in types, display initialization must be performed before use, and for custom types, the initialization responsibility falls on the constructor.
1 int x = 0; // display initialization x2 SubClass subClass; // use the default constructor of SubClass to initialize

 

The above term "Default initialization" describes the initialization status when the built-in type or custom type data is not displayed for initialization, "implicit initialization" describes the specific operation methods in this state. For example, for built-in types, the implicit initialization in the default initialization state is actually undefined, the implicit initialization of the custom type depends on its constructor.

As mentioned above, C ++ does not guarantee the initialization of built-in types, but when the built-in types are used as members of a class, under certain conditions, a member of the built-in type will be actively initialized by the compiler. This process is called numerical initialization. The following situations are listed in Accelerated C ++:
 1 #include <iostream>  2 #include <vector>  3 #include <map>  4 #include <string>  5   6 using std::cout;  7 using std::endl;  8 using std::vector;  9 using std::map; 10 using std::string; 11  12 class NumbericInitTestClass 13 { 14 public: 15     void PrintCounter() 16     { 17         cout <<"counter = " <<counter <<endl; 18     } 19 private: 20     int counter; 21 }; 22  23  24 int main() 25 { 26     NumbericInitTestClass tnc; 27     tnc.PrintCounter(); 28  29     map<string, int> mapTest; 30     cout <<mapTest["me"] <<endl; 31  32     vector<NumbericInitTestClass> vecNumbericTestClass(1); 33     vecNumbericTestClass[0].PrintCounter(); 34  35     return 0; 36 }

 

For a built-in type that is not initialized, it is an undefined value of 2009095316, and for two or three cases, it is initialized to 0, I have not thought of a suitable scenario for 1st cases. Looking back, for some similar terms in the book, it seems a little far-fetched to try to put them together :) Some rulesSeveral Basic initialization rules are attached here, most of which come from Objective C ++: 1. perform manual initialization for internal objects, because C ++ does not guarantee initialization of them. 2. It is best for constructors to use the member Initial Value column (member initialization list) instead of assigning values in the constructor. The member variables listed in the initial value column should be arranged in the same order as they are declared in the class. 3. C ++ does not like destructor to spit out exceptions. 4. Do not call virtual functions during constructor and destructor, because such calls never fall to derived class. 5. The copying function should make sure to copy "all member variables in the object" and "all base class components ".

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.