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

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

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


C++對象模型(14) - 3.6 Pointer to Data Members
作者: Jerry Cat
時間: 2006/11/23
鏈接:?
http://www.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的靜態(tài)數(shù)據(jù)成員. The value returned is of type

float*
not
float Point3d::*

because it refers to an specific single instance(靜態(tài)成員屬于類而非類的各具體實例對象), 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年6月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

常用鏈接

留言簿(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国产精品久久久久久久久久| 最新亚洲一区| 玖玖在线精品| 亚洲免费精品| 在线亚洲一区| 国产一区二区三区丝袜| 另类激情亚洲| 久久综合成人精品亚洲另类欧美| 久久精品理论片| 亚洲第一页自拍| 男人插女人欧美| 美女爽到呻吟久久久久| 欧美在线三区| 在线观看av不卡| 亚洲国语精品自产拍在线观看| 欧美黄色小视频| 亚洲伊人网站| 久久九九免费| 亚洲一级黄色av| 亚洲一区二区三区乱码aⅴ| 韩国一区二区三区在线观看 | 国产精品免费网站| 久久精品道一区二区三区| 久久亚洲视频| 亚洲欧美日韩专区| 麻豆精品在线观看| 亚洲综合色激情五月| 欧美综合激情网| 亚洲永久在线观看| 麻豆九一精品爱看视频在线观看免费| 一区二区日本视频| 久久九九有精品国产23| 亚洲视频在线观看免费| 老巨人导航500精品| 午夜天堂精品久久久久| 久久久91精品国产| 理论片一区二区在线| 亚洲深夜福利网站| 久久久久久久综合色一本| 正在播放亚洲| 欧美成人在线免费观看| 欧美在线三级| 国产精品久久网| 欧美激情视频一区二区三区在线播放| 亚洲卡通欧美制服中文| 欧美一区91| 午夜一区二区三视频在线观看| 免费亚洲婷婷| 免费观看在线综合| 国产午夜精品久久久久久久| 久久久久久久久综合| 一区二区三区免费在线观看| 久久夜色精品国产欧美乱| 欧美一区二区在线观看| 欧美丝袜第一区| 亚洲精品影院| 一本大道久久a久久综合婷婷| 乱中年女人伦av一区二区| 国产欧美日韩精品a在线观看| 国产精品主播| 国产亚洲欧美激情| 亚洲在线观看视频| 亚洲欧美日韩中文视频| 国产精品亚洲片夜色在线| 99在线热播精品免费99热| 亚洲精品国精品久久99热一| 久久久国产一区二区三区| 久久久水蜜桃av免费网站| 国产亚洲美州欧州综合国| 狂野欧美性猛交xxxx巴西| 亚洲精品视频一区二区三区| 久久精品国产一区二区三 | 中文无字幕一区二区三区| 亚洲国产成人91精品| 免费的成人av| 亚洲激情第一页| 日韩视频在线观看| 欧美日韩国产亚洲一区| 中国成人亚色综合网站| 欧美一区二区三区在线免费观看 | 久久久xxx| 亚洲黄色在线| 亚洲欧美中日韩| 国产午夜精品视频| 久久久久天天天天| 亚洲欧洲一区| 午夜欧美大片免费观看| 久久大逼视频| 久久精品色图| 亚洲电影激情视频网站| 久久综合久色欧美综合狠狠 | 亚洲国产一区二区视频| 久久亚洲风情| 亚洲欧洲一区二区三区| 欧美性jizz18性欧美| 欧美在线一级视频| 亚洲国产成人av好男人在线观看| 日韩午夜在线电影| 国产亚洲综合精品| 欧美另类视频| 久久精品一级爱片| 一本大道久久a久久精品综合| 久久精品盗摄| 亚洲一区二区伦理| 欧美四级剧情无删版影片| 亚洲免费高清| 欧美在线观看一二区| 亚洲国产中文字幕在线观看| 欧美日韩免费一区二区三区视频| 午夜精品成人在线| 亚洲国产毛片完整版| 欧美一区二区久久久| 亚洲精品久久久久久一区二区| 国产精品a久久久久| 91久久精品一区二区三区| 亚洲欧美视频一区二区三区| 狠狠色综合色区| 欧美视频日韩视频| 免费日韩成人| 久久激情视频| 亚洲欧美日韩第一区| 精品电影一区| 欧美经典一区二区三区| 午夜激情一区| 夜夜嗨网站十八久久| 久久中文字幕一区二区三区| 一区二区日韩精品| 国模私拍一区二区三区| 国产精品乱码一区二区三区| 欧美剧在线免费观看网站| 欧美在线免费观看视频| 亚洲欧美电影院| 国产精品99久久久久久久久 | 欧美日韩亚洲一区二区三区在线观看| 免费成人网www| 欧美自拍丝袜亚洲| 亚洲欧美另类国产| 亚洲一区三区视频在线观看| 日韩视频不卡中文| 亚洲精品一品区二品区三品区| 在线观看国产欧美| 国产精品a久久久久久| 久久精品一区四区| 欧美一区二区女人| 欧美在线黄色| 午夜激情综合网| 欧美一区二区三区播放老司机 | 欧美sm重口味系列视频在线观看| 久久久久久高潮国产精品视| 久久久久.com| 老鸭窝毛片一区二区三区| 男女精品网站| 亚洲国产欧美在线人成| 91久久香蕉国产日韩欧美9色| 欧美大片免费久久精品三p | 久久久www免费人成黑人精品 | 一区二区三区成人| 在线观看视频一区| 精品成人a区在线观看| 亚洲高清久久| 一区二区三区日韩精品| 亚洲午夜在线| 久久久国产一区二区| 免费观看亚洲视频大全| 亚洲精品欧美专区| 亚洲香蕉在线观看| 久久久久久久国产| 欧美裸体一区二区三区| 国产精品久久久久久久久久久久 | 亚洲午夜精品17c| 久久精品国产久精国产思思| 久久尤物视频| 欧美午夜精品久久久久免费视| 国产女人精品视频| 亚洲国产经典视频| 在线视频中文亚洲| 久久久综合精品| 久久久国产91| 亚洲福利在线观看| 一本一本久久a久久精品牛牛影视| 一本久道久久综合中文字幕| 欧美一区二区三区在线| 蜜臀久久久99精品久久久久久| 欧美特黄一区| 亚洲高清资源| 欧美主播一区二区三区美女 久久精品人 | 欧美成人综合网站| 欧美三区在线| 国产自产2019最新不卡| 91久久精品久久国产性色也91| 99这里只有精品| 久久青草久久| 99精品视频一区二区三区| 久久久久久尹人网香蕉| 国产精品剧情在线亚洲| 亚洲欧洲在线观看| 久久夜色精品国产欧美乱|