青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

asm, c, c++ are my all
-- Core In Computer
posts - 139,  comments - 123,  trackbacks - 0

/********************************************\
|????歡迎轉載, 但請保留作者姓名和原文鏈接, 祝您進步并共勉!???? |
\********************************************/


C++對象模型(14) - 3.6 Pointer to Data Members
作者: Jerry Cat
時間: 2006/11/23
鏈接:?
http://m.shnenglu.com/jerysun0818/archive/2006/11/23/15593.html


3.6 Pointer to Data Members:
;-----------------------------------------------------------------------

Consider the following Point3d class declaration. It declares a virtual function, a static data member, and three coordinate values:

class Point3d {
public:
?? virtual ~Point3d(); //虛表指針的位置"非頭即尾"
?? // ...
protected:
?? static Point3d origin;
?? float x, y, z;
};

What does it mean, then, to take the address of one of the coordinate members? For example, what value should the following yield?

&3d_point::z;
It is going to yield the z-coordinate's offset within the class object. Minimally, this has to be the size of the x and y members, since the language requires the members within an access level be set down in the order of declaration.

3.6 Pointer to Data Members
Pointers to data members are a somewhat arcane but useful feature of the language, particularly if you need to probe at the underlying member layout of a class. One example of such a probing might be to determine if the vptr is placed at the beginning or end of the class. A second use, presented in Section 3.2, might be to determine the ordering of access sections within the class. As I said, it's an arcane, although potentially useful, language feature.

Consider the following Point3d class declaration. It declares a virtual function, a static data member, and three coordinate values:

class Point3d {
public:
?? virtual ~Point3d();
?? // ...
protected:
?? static Point3d origin;
?? float x, y, z;
};
The member layout for each Point3d class object contains the three coordinate values in the order x, y, z and a vptr. (Recall that origin, the static data member, is hoisted outside the individual class object.) The only implementation aspect of the layout is the placement of the vptr. The Standard permits the vptr to be placed anywhere within the object: at the beginning, at the end, or in between either of the three members. In practice, all implementations place it either at the beginning or at the end.

What does it mean, then, to take the address of one of the coordinate members? For example, what value should the following yield?

&3d_point::z;
It is going to yield the z-coordinate's offset within the class object. Minimally, this has to be the size of the x and y members, since the language requires the members within an access level be set down in the order of declaration.

At the compiler's discretion, however, the vptr may be placed either before, in-between, or after the coordinate members. Again, in practice, the vptr is either placed at the beginning or at the end of the class object. On a 32-bit machine, floats are 4 bytes each, so we would expect the value to be either 8 bytes without an intervening vptr or 12 bytes with it. (The vptr, and pointers in general, use 4 bytes on a 32-bit architecture.)
?
That expectation, however, is off by one—a somewhat traditional error for both C and C++ programmers.

The physical offset of the three coordinate members within the class layout are, respectively, either 0, 4, and 8 if the vptr is placed at the end or 4, 8, and 12 if the vptr is placed at the start of the class. The value returned from taking the member's address, however, is always bumped up by 1. Thus the actual values are 1, 5, and 9, and so on. Do you see why Bjarne decided to do that?

The problem is distinguishing between a pointer to no data member and a pointer to the first data member. Consider for example:

float Point3d::*p1 = 0;
float Point3d::*p2 = &Point3d::x;

// oops: how to distinguish?
if ( p1 == p2 ) {
?? cout << " p1 & p2 contain the same value — ";
?? cout << " they must address the same member!" << endl;
}

To distinguish between p1 and p2, each actual member offset value is bumped up by 1. Hence, both the compiler (and the user) must remember to subtract 1 before actually using the value to address a member.

Given what we now know about pointers to data members, we find that explaining the difference between

&Point3d::z;
and
&origin.z

is straightforward. Whereas taking the address of a nonstatic data member yields its offset within the class, taking the address of a data member bound to an actual class object yields the member's actual address in memory. The result of

&origin.z
adds the offset of z (minus 1) to the beginning address of origin. origin是個實例化的類Point3d的靜態數據成員. The value returned is of type

float*
not
float Point3d::*

because it refers to an specific single instance(靜態成員屬于類而非類的各具體實例對象), much the same as taking the address of a static data member.

Under multiple inheritance, the combination of a second (or subsequent) base class pointer to a member bound to a derived class object is complicated by the offset that needs to be added. For example, if we have

struct Base1 { int val1; };
struct Base2 { int val2; };
struct Derived : Base1, Base2 { ... };

void func1( int d::*dmp, d *pd )
{
?? // expects a derived pointer to member
?? // what if we pass it a base pointer?
?? pd->*dmp;
}
void func2( d *pd )
{
?? // assigns bmp 1
?? int b2::*bmp = &b2::val2;

?? // oops: bmp == 1,
?? // but in Derived, val2 == 5
?? func1( bmp, pd )
}
bmp must be adjusted by the size of the intervening Base1 class when passed as the first argument to func1(). Otherwise, the invocation of

pd->*dmp;
within func1() will access Base1::val1, not Base2::val2 as the programmer intended. The specific solution in this case is

// internal transformation by compiler
func1( bmp + sizeof( Base1 ), pd );
In general, however, we cannot guarantee that bmp is not 0 and so must guard against it:

// internal transformation
// guarding against bmp == 0
func1( bmp ? bmp + sizeof( Base1 ) : 0, pd );

二. Efficiency of Pointers to Members:

The following sequence of tests attempts to gain some measure of the overhead associated with using pointers to members under the various class representations of the 3D point. In the first two cases, there is no inheritance. The first case takes the address of a bound member:

float *ax = &pA.x;
for the three coordinate members of points pA and pB. The assignment, addition, and subtraction look as follows:

*bx = *ax - *bz;
*by = *ay + *bx;
*bz = *az + *by;
The second case takes the address of a pointer to data member:

float pt3d::*ax = &pt3d::x;
for the three coordinate members. The assignment, addition, and subtraction use the pointer to data member syntax, binding the values to the objects pA and pB:

pB.*bx = pA.*ax - pB.*bz;
pB.*by = pA.*ay + pB.*bx;
pB.*bz = pA.*az + pB.*by;
Recall that the direct data member exercise of this function, executed in Section 3.5, ran with an average user time of 0.80 with optimization turned on and 1.42 with optimization turned off for both compilers. The results of running these two tests, coupled with the results of the direct data access, are shown in Table 3.3:

Table 3.3. Nonstatic Data Member Access
???
???????????????????? Optimized?????? Non-optimized

Direct Access??????? 0.80????????????? 1.42
Pointer to
?? Bound Member????? 0.80????????????? 3.04
?
Pointer to
?? Data Member
????? CC???????????? 0.80????????????? 5.34
????? NCC??????????? 4.04????????????? 5.34


The non-optimized results conform to expectations. That is, the addition of one indirection per member access through the bound pointer more than doubles the execution time. The pointer-to-member access again nearly doubles the execution time. The binding of the pointer to data member to the class object requires the addition of the offset minus 1 to the address of the object. More important, of course, the optimizer is able to bring the performance of all three access strategies into conformance, except the anomalous behavior of the NCC optimizer. (It is interesting to note here that the appalling performance of the NCC executable under optimization reflects a poor optimization of the generated assembly code and not an attribute of the source-level C++ code. An examination of the generated non-optimized assembly for both CC and NCC showed the two outputs to be identical.)

The next set of tests looks at the impact of inheritance on the performance of pointers to data members. In the first case, the independent Point class is redesigned into a three-level single inheritance hierarchy with one coordinate value as a member of each class:

class Point { ... }; // float x;
class Point2d : public Point?? { ... }; // float y;
class Point3d : public Point2d { ... }; // float z;
The next representation retains the three-level single inheritance hierarchy but introduces one level of virtual inheritance: the Point2d class is virtually derived from Point. As a result, each access of Point::x is now accessing a virtual base class data member. Then, more out of curiosity than need, the final representation added a second level of virtual inheritance, that of Point3d being virtually derived from Point2d. Table 3.4 shows the results. (Note: The poor performance of the NCC optimizer was consistent across the tests, so I've left it off the listing.)

Table 3.4. Pointer to Data Member Access
???
???????????????????? Optimized?? %?? Non-optimized
?
No Inheritance?????? 0.80????????????? 5.34
SI (3 levels)??????? 0.80????????????? 5.34
VI (1 level)???????? 1.60????????????? 5.44
VI (2 level)???????? 2.14????????????? 5.51
?
SI:? Single Inheritance?????? VI:? Virtual Inheritance


Because inherited data members are stored directly within the class object, the introduction of inheritance does not affect the performance of the code at all. The major impact of introducing virtual inheritance is to impede the effectiveness of the optimizer. Why? In these two implementations, each level of virtual inheritance introduces an additional level of indirection. Under both implementations, each access of Point::x, such as

pB.*bx
is translated into
&pB->__vbcPoint + ( bx - 1 )

rather than the more direct
&pB + ( bx - 1 )

The additional indirection reduced the ability of the optimizer to move all the processing into registers.

posted on 2006-11-23 20:23 Jerry Cat 閱讀(1192) 評論(0)  編輯 收藏 引用

<2006年11月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用鏈接

留言簿(7)

隨筆檔案

最新隨筆

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲激情视频在线播放| 激情欧美日韩| 亚洲综合首页| 中文在线资源观看网站视频免费不卡| 欧美激情欧美狂野欧美精品| 99精品国产福利在线观看免费| 亚洲精品一区二区在线| 欧美日韩在线另类| 欧美一区二区三区男人的天堂| 午夜精品一区二区三区在线| 激情综合色综合久久| 亚洲国产成人91精品| 欧美高清一区| 亚洲欧美亚洲| 你懂的成人av| 午夜精品剧场| 女仆av观看一区| 午夜精品99久久免费| 欧美一区二区三区的| 日韩一区二区久久| 午夜精品久久久久| 日韩写真视频在线观看| 亚洲一区二区三区在线| 亚洲激情另类| 亚洲欧美国产一区二区三区| 亚洲第一福利视频| 亚洲一区二区三区精品在线| 尤物99国产成人精品视频| 亚洲精品美女在线观看| 好看的日韩视频| av不卡免费看| 最新中文字幕一区二区三区| 亚洲欧美日本国产专区一区| 亚洲欧洲日韩女同| 西瓜成人精品人成网站| 99re热精品| 久久夜色精品国产亚洲aⅴ| 亚洲一区二区三区在线观看视频| 久久久综合网| 久久国产精品久久久| 欧美视频一区| 91久久国产综合久久91精品网站| 国内精品亚洲| 午夜久久电影网| 亚洲欧美中文另类| 欧美日韩三级一区二区| 亚洲丰满少妇videoshd| 狠狠色香婷婷久久亚洲精品| 亚洲欧美日韩爽爽影院| 亚洲午夜一区二区| 欧美久久婷婷综合色| 欧美激情一区二区三区蜜桃视频| 国产综合色产在线精品| 午夜精品久久久久久久久久久久| 亚洲天堂久久| 欧美色视频一区| 日韩视频精品在线| 日韩午夜在线观看视频| 欧美成人在线影院| 欧美激情一二区| 亚洲国产午夜| 久久在线免费观看视频| 麻豆久久婷婷| 亚洲人成毛片在线播放| 欧美69视频| 最新69国产成人精品视频免费| 亚洲精品在线看| 欧美巨乳波霸| 亚洲午夜久久久久久久久电影网| 亚洲影院污污.| 国产精品天天摸av网| 亚洲一区区二区| 久久国产高清| 影音先锋中文字幕一区二区| 久久这里只有| 亚洲日本激情| 亚洲免费在线| 好男人免费精品视频| 麻豆91精品91久久久的内涵| 亚洲福利视频二区| 一区二区三区免费网站| 欧美午夜精品理论片a级按摩| 亚洲小视频在线| 久久精品国产一区二区电影| 在线观看一区视频| 欧美精品成人| 午夜视频精品| 欧美大片第1页| 亚洲午夜一二三区视频| 国一区二区在线观看| 欧美xart系列在线观看| 在线视频精品一区| 久久免费观看视频| av成人老司机| 狠狠v欧美v日韩v亚洲ⅴ| 欧美1区视频| 欧美一级视频| 亚洲日本黄色| 麻豆精品在线播放| 亚洲影院色在线观看免费| 黄色工厂这里只有精品| 欧美日韩成人一区二区三区| 午夜在线一区| 一本大道久久a久久精品综合| 久久久水蜜桃av免费网站| 99精品国产在热久久| 国外成人在线视频网站| 欧美日韩国内| 久久阴道视频| 亚洲欧美一区二区原创| 亚洲激情国产精品| 久久久蜜桃一区二区人| 在线亚洲欧美视频| 亚洲激情国产精品| 国产亚洲制服色| 国产精品久久久久一区二区三区| 久热精品在线| 欧美在线观看视频| 亚洲无限av看| 亚洲另类视频| 亚洲黄色免费电影| 久久嫩草精品久久久精品| 亚洲淫性视频| 一区二区三区四区蜜桃| 亚洲国产成人tv| 一区二区三区在线免费播放| 国产精品日韩在线| 欧美性色综合| 欧美日韩综合另类| 欧美日韩国产bt| 欧美黄色影院| 欧美激情中文不卡| 欧美成年网站| 国模 一区 二区 三区| 国产精品一区在线观看| 欧美日韩精品一区二区三区四区| 欧美国产日韩xxxxx| 你懂的国产精品永久在线| 久久一区视频| 蜜臀av性久久久久蜜臀aⅴ| 久久亚洲精品伦理| 另类尿喷潮videofree| 久久人人爽国产| 免费欧美在线| 欧美激情在线狂野欧美精品| 欧美激情影院| 国产精品xxxxx| 国产精品一区二区久久精品 | 亚洲少妇自拍| 亚洲永久在线| 欧美专区在线播放| 久久久久久久网| 男同欧美伦乱| 欧美日韩午夜激情| 国产精品av久久久久久麻豆网| 国产精品草草| 国产一区二区三区成人欧美日韩在线观看| 国产欧美精品| 在线成人激情| 亚洲图片在线观看| 久久er99精品| 欧美大片免费看| 一区二区三区欧美| 欧美亚洲在线播放| 免费日本视频一区| 欧美日韩一区二区精品| 国产精品嫩草影院一区二区| 国产亚洲视频在线观看| 亚洲国产欧美久久| 亚洲一级二级在线| 久久亚洲图片| 日韩午夜电影av| 欧美一区亚洲| 欧美另类一区二区三区| 国产精自产拍久久久久久| 一色屋精品视频免费看| 中文av一区二区| 久久亚洲综合色一区二区三区| 亚洲黄色成人| 香蕉久久久久久久av网站| 免费视频一区| 国产一区二区日韩| 一区二区三区不卡视频在线观看 | 久久精品国产精品 | 欧美在线观看一区| 欧美日韩不卡视频| 精品盗摄一区二区三区| 一区二区欧美在线| 可以看av的网站久久看| 亚洲视频欧美视频| 欧美激情视频一区二区三区在线播放 | 一本久久精品一区二区| 久久久精品999| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 国产精品一区免费观看| 亚洲免费av网站| 免费短视频成人日韩| 亚洲欧美在线一区二区| 欧美视频一区二区三区…| 91久久精品美女|