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

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

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


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的靜態(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 閱讀(1211) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理



<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>
            亚洲激情视频网| 欧美成年人视频| 久久精品国产在热久久| 久久综合伊人77777| 欧美国产视频日韩| 国产亚洲一区二区三区在线观看| 精品999在线观看| 亚洲无玛一区| 麻豆九一精品爱看视频在线观看免费 | 亚洲人成网在线播放| 亚洲午夜久久久| 在线视频欧美日韩| 另类成人小视频在线| 亚洲理论电影网| 久久久久久91香蕉国产| 亚洲日本成人| 国产精品日本一区二区| 99re热精品| 嫩草影视亚洲| 亚洲欧美亚洲| 国产精品爽黄69| 久久综合国产精品| 久久国产直播| 国产亚洲一区二区三区在线观看| 免费亚洲婷婷| 久久精品在这里| 日韩亚洲欧美在线观看| 中文一区二区| 亚洲欧洲一区二区天堂久久| 免费观看成人网| 欧美啪啪成人vr| 亚洲国产精品久久久久秋霞蜜臀| 久久精品在线播放| 欧美激情在线有限公司| 亚洲精品资源美女情侣酒店| 亚洲永久精品大片| 国产女人aaa级久久久级| 亚洲永久在线| 亚洲综合首页| 国产在线观看91精品一区| 久久成人18免费网站| 亚洲欧美日韩成人| 99精品欧美一区| 久久视频一区| 亚洲国产日韩精品| 性欧美大战久久久久久久久| 精品动漫3d一区二区三区免费| 夜夜嗨av色一区二区不卡| 欧美区高清在线| 免费亚洲电影| 国内在线观看一区二区三区| 久久综合九色九九| 国产精品一区免费视频| 久久亚洲视频| 国产日韩欧美中文在线播放| 老司机午夜精品| 国产深夜精品福利| 亚洲欧美激情诱惑| 亚洲欧美日韩国产综合| 久久aⅴ国产欧美74aaa| 91久久午夜| 久久综合国产精品| 久久综合九色综合欧美狠狠| 国产日韩欧美视频在线| 亚洲欧美日本日韩| 性感少妇一区| 美女尤物久久精品| 亚洲自拍高清| 国产精品日韩精品| 亚洲欧美中文日韩v在线观看| 午夜精品久久久久久99热软件 | 久久久久久高潮国产精品视| 国产毛片一区二区| 欧美一区二区免费视频| 99在线精品观看| 欧美一区二区三区免费在线看| 欧美一区二区三区免费大片| 欧美精品免费视频| 一本大道久久精品懂色aⅴ| 国产精品99久久久久久久久久久久 | 欧美在线一区二区| 国产一区视频观看| 久久久久久亚洲精品中文字幕 | 最新亚洲一区| 欧美人与禽猛交乱配视频| 一区二区三区四区五区精品视频| 狠狠色狠狠色综合日日五| 久久综合狠狠综合久久激情| 亚洲国产片色| 加勒比av一区二区| 欧美成人免费在线视频| 一本一本久久a久久精品综合麻豆| 午夜国产不卡在线观看视频| 国产一区二区中文字幕免费看| 久久在线视频| 亚洲手机成人高清视频| 亚洲最新色图| 国产网站欧美日韩免费精品在线观看| 久久激情五月激情| 亚洲免费成人av| 一区二区av| 国产亚洲欧洲| 欧美激情免费在线| 欧美在线免费| 亚洲人人精品| 久久久久久久综合日本| 欧美激情在线狂野欧美精品| 亚洲一卡二卡三卡四卡五卡| 蜜臀av国产精品久久久久| 一区二区三区免费在线观看| 欧美日韩黄色一区二区| 亚洲美女毛片| 免费在线成人| 欧美亚洲网站| 亚洲一区在线视频| 亚洲国产日韩一区| 国产亚洲福利| 国产精品乱人伦一区二区| 日韩视频国产视频| 免费视频亚洲| 久久精品国产成人| 尤物在线精品| 欧美华人在线视频| 久久影院午夜论| 欧美在线免费| 午夜久久99| 亚洲一区二区av电影| 亚洲理伦电影| 欧美一区二区成人6969| 在线一区二区日韩| 亚洲乱码一区二区| 亚洲欧洲视频| 亚洲人精品午夜在线观看| 狠狠噜噜久久| 国产真实乱偷精品视频免| 国产精品视频久久一区| 欧美日韩中文字幕在线视频| 亚洲综合色自拍一区| aⅴ色国产欧美| 亚洲精品久久久一区二区三区| 欧美**人妖| 欧美成人黑人xx视频免费观看| 久久午夜影视| 葵司免费一区二区三区四区五区| 久久久精品日韩| 久久久之久亚州精品露出| 久久精品免视看| 久久久综合香蕉尹人综合网| 久久99伊人| 久久亚洲不卡| 欧美国产视频日韩| 在线亚洲精品福利网址导航| 在线视频精品一区| 亚洲天堂av电影| 午夜视频在线观看一区| 欧美综合77777色婷婷| 久久亚洲综合色| 亚洲电影免费观看高清完整版在线观看 | 午夜一区在线| 久久久久久久久久码影片| 久久一区二区三区超碰国产精品| 美女精品国产| 欧美激情2020午夜免费观看| 欧美日韩中文在线| 国产欧美精品在线| 怡红院精品视频| 亚洲人成在线观看一区二区| 亚洲深夜影院| 久久国产精品亚洲va麻豆| 美女网站久久| 99精品久久| 久久久久久久一区二区三区| 欧美激情一区二区三区在线视频| 欧美午夜影院| 欧美日韩中文字幕| 国产在线拍偷自揄拍精品| 亚洲精品国产精品久久清纯直播 | 欧美高清视频一区二区| 欧美涩涩视频| 永久免费毛片在线播放不卡| 在线一区视频| 久久美女性网| 亚洲精品影视在线观看| 欧美一区二区三区精品| 欧美激情五月| 黄色国产精品| 亚洲欧美日韩在线高清直播| 欧美 日韩 国产一区二区在线视频| 一区二区三区蜜桃网| 老司机精品福利视频| 国产精品网站在线| 亚洲精品一区二区三区樱花| 久久精品论坛| 中文日韩在线视频| 欧美成黄导航| 亚洲高清在线视频| 久久久精品tv| 亚洲字幕一区二区| 欧美性色综合| av成人动漫|