Some questions in data semantics

Source: Internet
Author: User

Today and the small partners to discuss the third chapter of data semantics refers to some of the knowledge, it is necessary to summarize, it seems not to summarize knowledge will slip away, so take the night to write it.
First look at an example of such an inheritance:

class X{ };class Y: public virtualX { };class Z: public virtualX { };class A: public Y,publicZ { };

The results are 1, 8, 8, 12, respectively, for the X Y Z A. Of course my machine is 1, 4, 4, 8. Generally the old machine will be the first result, because the compiler is older.
Explain the first question: why the sizeof of x would be 1. This is because, regardless of the old compiler or the new compiler, an empty class X is placed with a char, which guarantees that the two objects of Class X can be configured with a unique address in memory.
Note: This starts with the old compiler.
A second conclusion: the old compiler will have a char for all empty classes. So Y's memory has a char (1 bytes), and a pointer to the virtual base class (4 bytes), in order to justify, plus 3 bytes, so y is a total of 8 bytes. Similarly z is also 8 bytes.
A third conclusion: the size of Class A. The size of a is determined by the size of the X +y (meaning to subtract the size that is configured to satisfy the virtual inheritance base class X), and the simple size of the +z. Note that X is a virtual base class, and the virtual base class will have only one instance of the derived system, so even if a inherits Y and Inherits Z, it has only one instance of X (1 bytes), plus 3 bytes, so it is 4 bytes. The pure size of Y, the total size of Y is 8 bytes, the head pointer (4 bytes) is configured to satisfy the virtual inheritance base class X, then the simple size is 4 bytes, and the pure size of Z is 4 bytes, so the size of a is 12 bytes. This answers the old compiler 1,8,8,12 case.
Note: Here's the beginning of the new compiler 1,4,4,8 case. It was also my own measurement of the situation.
First, the size of Class X is still 1 bytes. Because of the placement of a char.
Second, Y does not need to place a char again. The new compiler treats the empty virtual base class as the first part of the derived class (which is understood here as the member of Y), and the derived class Y has at least 4 bytes in memory, so the corresponding objects of class Y is already distinguishable in memory, so no more char is required. So y and Z are all 4 bytes (all configured with a pointer to satisfy the virtual inheritance).
Finally, the 8 bytes of a. Because a inherits Y and Z, the size of a is the sum of YZ 8, and the char that is placed on the instance of Class X can be taken away because a is not empty in memory, so a is 8 bytes.
Final conclusion: How big a class is. A: All nonstatic data members (non-static) are accommodated, plus the additional data member (such as VPTR) that the compiler automatically adds to support certain language features. Finally add the need for alignment (boundary alignment).

the binding problem for the data member.

Here's a question, code like this:

extern floatx;class Point3d{public:    Point3d(float,float,float);    //问题:被传回和被设定的x是哪个x呢    const { returnx; }    voidX(float new_x)const{ x = new_x; }    //..private:    floatx, y, z;};

When the old-fashioned compiler is processing, the line that encounters the first x will parse x into the global X, causing some errors.
The new compiler does not perform data-binding operations on a class's functions until the closing parenthesis of the class declaration is met. This avoids the binding error of the data.
However, when a new compiler is confronted with a problem of this type of data (the problem is the following),

typedef intlength;class Point3d{public:    //喔欧:length 第一次遇见,就被决议(resolved)为global    //_val会被决议为Point3d::_val,这个没问题。    valval; }    return _val; }    //..private:    typedeffloatlength;    length _val;    //..};

In such a problem, members of the resolution is not a problem, because the new compiler and other classes are all declared after the resolution _val, so _val is correctly parsed into the class _val. However, the data type length cannot be parsed correctly to the length of the class we want. In this case, even in the modern compiler, you should take defensive procedural style: always put "nested type declaration" at the beginning of class. This ensures that the bindings are correct.

layout issues for data members.

Look at a class like this, how his data members are laid out.

class Point3d{public:    // ..private:    float x;    static List<Point3d*> *freeList;    float y;    staticconstint250;    float z;};

A: All static data members are not placed in the object's layout, and non-static data members are arranged in the same order as they are declared in the class object.
also, as mentioned earlier, the compiler adds some data members that are used internally, such as Vptr. The C + + standard allows the compiler to arbitrarily place these internally generated data members, and in general, some compilers place vptr at the forefront of class objects.

The processing of the section,

The example code is as follows:

class Point3d{public:    // ..private:    float x;    static List<Point3d*> *freeList;private:    float y;    staticconstint250;private:    float z;};

Conclusion: The compiler will chain all access sections together to form a block in the order in which they are declared. How much of this section does not bring a burden. That is: Declare 8 variables in a section, and declare a variable in each of the 8 sections to get the same size as the object.

The access difference problem of data members.

That is to consider them

origin.x = 0.0;pt->x = 0.0;

The access difference.

For static data members:

Static member are not actually in class object, so accessing static data members does not need to pass class object. So when accessing a static data member, there is no additional cost, it takes out its address directly in the program's global area. Small add: If there are two classes, they all declare a static member FreeList, then if they are placed directly in the program's data segment, it will cause a name conflict. At this time the compiler will secretly encode each static data member to obtain a unique program identification code, which is collectively known as name-mangling.

For non-static data members:

The first thing to know is that a non-static data member actually has an implied class object pointer, which is the this pointer. For access operations of non-static data members, the address of the class object is required plus the offset address of the data member. The offset address of the data member is known at compile time, even if the data member is derived derived from, and so on, the offset address can be obtained, thus accessing origin.x, only the address of the object origin, and the offset of x, so when accessing origin.x=0.0, Its efficiency and access to a C struct member or a nonderived class member is the same.
When virtual inheritance occurs, the situation is different, consider the following code:

Point3d *pt3d;pt3d->_x = 0.0;


In this case, when _x is a struct member, a class member, single inheritance, multiple inheritance, is exactly the same. But if _x is a virtual base class member, the access speed will be slightly slower.

Point3d origin, *pt=&origin;origin.x = 0.0;pt->x = 0.0;

What are the major differences?
Answer: When Point3D is a derived class (derived class) and has a virtual base class in its inheritance structure, and X is the member inherited from that virtual base class, There will be significant differences. Because at this point we can't say what type of class The PT is necessarily pointing to (so we don't know the actual offset address of the compile time, this member X), so this access must be deferred to the execution period, which can be resolved by an additional indirect boot. But if there is no such problem with origin, the type is undoubtedly the Point3D class, and it inherits the offset address of the members from the virtual base class, which is fixed at compile time. In my words: PT is declared as a Point3D pointer, which is fine, but PT can point to objects of other class types, such as objects to derived classes of Point3D, objects of derived classes of derived classes, and so on. The offset position of X of different class type is different, so at compile time, see PT, can only see the pointer that he declares is Point3D , but cannot calculate the offset position of x according to the X offset position of the Point3D class. It can only be determined at run time, so in this case, the efficiency slows down a bit. This is also a cost of polymorphism (this sentence is to be verified).

First come here, if there is error or wrong, welcome to discuss and correct.

Some questions in data semantics

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.