2010-10-08

standard-layout classのささいな条件

あるクラスがstandard-layout classの条件を満たしたときに保証される動作はいくつかあるが、その中でもとくに重要なものに、クラスのオブジェクトへのアドレスは、クラスの最初の非staticデータメンバーのサブオブジェクトへのアドレスに等しい。というものがある。

struct A
{
    int x ; int y ;
} ;

A a ;

A * a_ptr = &a ;
int * ptr = reinterpret_cast<int *>( a_ptr ) ;

この場合、ptrはa.xを指す。これは規格で保証されている。ちなみにこの時、++ptrがa.yを指す保証はない。なぜならば、実装はデータメンバーの間にpaddingを入れるかもしれないからだ。ともかく、このクラスのオブジェクトへのアドレスが、クラスの最初の非staticデータメンバーへのサブオブジェクトのアドレスに等しいというのは、重要な保証だ。

ところで、standard-layout classとなるためには、かなり厳しい条件を満たさなければならないわけだが、その中に、「最初の非staticデータメンバーと、基本クラスとで、同じ型を使わない」というものがある。

// standard-layout classではない例
struct A { } ;
struct B : A // 基本クラス
{
    A a ; // 最初の非staticデータメンバー
    int data ; // 二つ目の非staticデータメンバー
} ;

なぜかというと、基本クラスのサブオブジェクトと、データメンバーaは、別々のアドレスを割り当てられていなければ、困るからだ。

struct A { } ;
struct B : A { A a ; } ;

B obj ;

A * p1 = &obj ; // 基本クラスのサブオブジェクトへのアドレス
A * p2 = &obj.a ; // データメンバーへのアドレス

// p1 != p2が保証される

なぜならば、クラスBに、クラスAというサブオブジェクトは、二つあるからだ。p1 != p2を保証するためには、このようなクラスには、standard-layout classになってもらっては困る。

No comments:

Post a Comment

You can use some HTML elements, such as <b>, <i>, <a>, also, some characters need to be entity referenced such as <, > and & Your comment may need to be confirmed by blog author. Your comment will be published under GFDL 1.3 or later license with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.