Do not be fooled by C ++ (automatically generated Rules)

Source: Internet
Author: User

The C ++ object can be created in two ways: constructor and copy constructor. Suppose we define class A and use it to create an object.

Copy codeThe Code is as follows: A a, B;
A c =;
A d (B );

Objects a and B are created using the default constructor A: A () provided by the compiler. We call this creation method the definition of the object (including the meaning of the Declaration ). Objects c and d use existing objects and are created through the copy constructor A: A (const A &) provided by the compiler, this method is called object initialization (including definition and Declaration ).

Many may confuse object initialization with object assignment, for example.

Copy codeThe Code is as follows: c = d;

Here, assigning object d to object c is not a new object, and it does not call any constructor. The default value assignment operator const A & operator = (const A &) provided by the compiler supports this statement.

In addition to providing default constructor, copy constructor, and value assignment operator overload functions, the compiler may also provide the Destructor ::~ A (), but the Destructor here is not virtual (I believe some kids will forget this ).

These basic syntaxes are perhaps no stranger to those who have learned C ++. Since we have learned object-oriented C ++, we have always known that compilers provide us with such convenience. After years of programming practice and experience, we absolutely believe that the compiler does this for us, because we have never encountered any problems. Even in our minds, a concept is formed by default-even if I define an empty class (nothing in the class), the compiler will still generate the four functions mentioned above for us.

If you have formed such an idea, congratulations, because you have used the basic C ++ rules very skillfully. Unfortunately, you and I have seen the tip of the iceberg, and the compiler works much less like we use it. Readers may wonder, isn't the compiler generating these functions? A: It depends on the definition of your class. Then how does the compiler generate these functions? Like me, curious people want to find out, and The content is thoroughly interpreted in "Inside The C ++ Object Model. The author also shares the object structures described in this book with his personal understanding.

First, let's talk about it in the simplest way. Does the compiler generate constructor for the class? Based on the example described above, if there is only one empty class definition, we can definitely say-no. We don't have to be surprised by the compiler. Imagine an empty class-No data member or member function. What can be done even if a constructor is generated? Even if it is generated, it is just an empty constructor.

Copy codeThe Code is as follows: (){}

It can do nothing and does not have to do anything. Even more tragic, its appearance not only has no positive significance, but also adds completely unnecessary function call burden to the compiler and program running.

In this case, we make this class more complex. We add data members and member functions for it, such as the following code (we remember it as Example 1 ).

Copy codeThe Code is as follows: class
{
Public:
Int var;
Void fun (){}
};

Even so, the result is the same as the above, and no constructor is generated! Because there is no reason to initialize var, And the compiler does not know what value to use for initialization.


Indeed, no constructor is called after object a is defined in the main function.

May someone say that initialization with 0 is not feasible? This is just our wishful thinking. The value of a variable without initialization can be uncertain. Why should we generate a statement with initialization 0 meaningless.

How can the compiler generate Constructors ?! Maybe you are a little crazy like me. But now it's not desperate, because the compiler needs us to give it a "legitimate reason" to generate constructors. There are four legitimate reasons for the compiler to have to generate constructors. Here we will introduce them one by one.

First, modify the var type. Suppose it is not a built-in type int, but a defined class B.

B var;

Can changing the data member type to a custom type affect the choice of the compiler? A: Yes. This depends on whether Class B has a defined constructor. The reader may have understood A bit. Yes, if B does not define the constructor (like A here), then the compiler still has no reason to generate the constructor-What to initialize for B? Otherwise, once B defines the default constructor B: B (), even if it is empty, the compiler has to create A default constructor for A (in-depth optimization of the compiler is not considered here ). Because the object of A needs to use the default constructor of B to initialize its own member var, although the constructor of B does not do anything. Because the compiler cannot assume what operations B's constructor performs (to the extreme, what if a global variable is modified ?), Therefore, it is absolutely necessary for the compiler to generate A constructor to ensure that the constructor of B type data members can be normally executed.

Go to the constructor generated by the compiler for A. We found the statement called by the constructor for B (selected row ).

Of course, if B provides constructor, but it is not the default constructor, the programmer must be involved in var initialization. Otherwise, the compiler will be rude-error!

Therefore, the first legitimate reason for the compiler to generate the default constructor is --The data member in the class is an object, and the class of this object provides a default constructor.

Now, let's go back to Example 1. Here we don't modify the var type, but let A inherit from another class C.

Copy codeThe Code is as follows: class A: public C

As we all know, in the C ++ constructor initialization syntax, the constructor first initializes the base class C and then initializes its own data members or objects. Therefore, the problem here is similar to the object member var. If the base class C does not provide any constructor, the compiler still does not provide the default constructor of. If C provides the default constructor, the result is similar to that of the front side.

As expected, the compiler generates constructor for Class A and calls the default constructor defined by Class C. Similarly, if C does not provide the default constructor and other constructor functions are provided, compilation fails.

This is the second legitimate reason for the compiler to generate the default constructor --The base class of the class provides the default constructor..

Let's go back to Example 1 again. This time we modified the member function fun.

Copy codeCode: virtual void fun (){}

We changed the member function fun of Class A to A virtual function and checked whether the default constructor was generated.

This time, the compiler generates A default constructor for A, although it does not call any other constructor! Why? Originally, C ++ needed to maintain a virtual function table (vftable) for the class to implement the polymorphism mechanism ), the object of each class saves a pointer to the virtual function table (usually stored in the four nodes at the beginning of the object. The implementation of the polymorphism mechanism is not introduced here ). The compiler generates A constructor for A. It is actually nothing else. To ensure that all the objects it defines must initialize the pointer to this virtual function table (vfptr )!

Okay, so we get the third legitimate reason for the compiler to generate the default constructor --Class defines virtual functions. This may also involve a more complex scenario: the class itself does not define virtual functions, but inherits the virtual functions of the base class. In fact, according to the above principles, we can infer the following: Since the base class defines virtual functions, the base class itself needs to generate the default constructor to initialize its own virtual function table pointer. Once the base class generates a default constructor, the derived class needs to generate a default constructor to call it. At the same time, if you understand the polymorphism mechanism, the derived class will initialize the virtual function table pointer once in the generated default constructor.

Finally, let's go back to Example 1 again. This time we still let A inherit from C, but this time C is an empty class-nothing, and no default constructor will be automatically generated. However, the method that A inherits from C must be changed.

Copy codeThe Code is as follows: class A: public virtual C

A Virtual Machine inherits from C. What is the difference this time?

This time, the compiler also generates the constructor, and the initialization process is A bit similar to that of the virtual function. After careful observation, we found that this constructor also initialized a table-vbtable. Readers who understand the virtual Inheritance Mechanism should be familiar with it. This table is called a virtual base table, it records the offset position of all the virtual base class sub-objects inherited by the class in the objects defined in this class (we will discuss the implementation of the virtual Inheritance Mechanism in detail later ). To ensure that the virtual Inheritance Mechanism works properly, an object must maintain a pointer to the table during initialization, which is called a virtual table pointer (vbptr ). The compiler provides the default constructor of A for A reason similar to that of virtual functions.

In this way, we can find the fourth legitimate reason for the compiler to generate the default constructor --Class uses virtual inheritance.

Here, we have explained the legitimate reasons for the compiler to generate default constructor for the class. I believe you should have a general understanding of the time when the constructor is generated. These four "legitimate reasons" are actually the reason why the compiler has to generate Default constructors for the class, in The "Inside The C ++ Object Model", this reason is called nontrival (The sir translation is awkward, so how to translate it with you ). In addition to these four cases, the compiler is called trival, that is, there is no need to generate a default constructor for the class. The constructor generation Criterion discussed here is written into the C ++ Standard. In this case, the Standard is a set of criteria that "fit the normal thinking" (simply YY). This is actually the case, the compiler should not do unnecessary work for consistency.

By discussing the default constructor, we believe that the generation time of the copy constructor, the value assignment operator overload function, and the Destructor should be automatically scalable. Yes, they follow the most fundamental principle:Only when the compiler has to generate a function for this class (Nontrival), The compiler will actually generate it..

Therefore, as the title says, we should not be fooled by the rules described in the C ++ syntax. Indeed, I believe that these generation rules will not have much impact on our programming (no errors), but only by understanding the operations behind them can we know what the compiler has done for us, we only know how to use C ++ to make it more efficient-such as eliminating unnecessary constructor and virtual mechanisms (if possible ). I believe that the description of the automatically generated content in C ++ makes many people recognize the cause and effect of the object constructor. I hope this article will help you.

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.