5

重複の可能性:
クラスはデータ メンバーをシーケンシャル メモリに格納しますか?

以下が正しい理由を尋ねたかっただけです。

template<class T>
class Vec3 {
public:
  // values
  T x,y,z;

  // returns i-th komponent (i=0,1,2) (RHS array operator)
  const T operator[] (unsigned int i) const {
    return *(&x+i);
  }
}

つまり、x、y、および z が常にメモリ内で sizeof(T) 単位離れていることが常に保証されるのはなぜですか。これらの 2 つの変数の間にフラグメンテーション ホールが存在し、この演算子が偽の値を返すことはあり得ないのでしょうか?

4

2 に答える 2

6

、、およびが常にメモリ内でユニット離れていることは保証されていません。間にパディングバイトを追加することができます。 実装の詳細として省略されています。 保証されるのは、クラス/構造の先頭とPOD構造/クラスの最初のメンバーの間にパディングがないことだけです。xyzsizeof(T)

operator[]コード内のの実装が常に機能することは保証されていません。

参照:
C ++ 11:9.2クラスメンバー[class.mem]

14)同じアクセス制御(条項11)を持つ(非ユニオン)クラスの非静的データメンバーは、後のメンバーがクラスオブジェクト内でより高いアドレスを持つように割り当てられます。アクセス制御が異なる非静的データメンバーの割り当て順序は指定されていません(11)。実装の調整要件により、2つの隣接するメンバーがすぐに割り当てられない場合があります。仮想関数(10.3)と仮想基本クラス(10.1)を管理するためのスペースの要件も同様です。

于 2013-01-16T14:48:43.920 に答える
0

フラグメンテーション ホールを回避するために、次の方法でアラインメントを制御できます。

#ifdef compiling_with_msvc
#pragma pack(1)
#endif
template<class T>
class Vec3 {
public:
    // values
    T x,y,z;

    // returns i-th komponent (i=0,1,2) (RHS array operator)
    const T operator[] (unsigned int i) const {
        return *(&x+i);
    }
#ifdef compiling_with_gcc
}__attribute__((packed));
#else
};
#endif

C++11 コンパイラを使用できる場合は、標準的な方法でアラインメントを制御できます。

ただし、クラスのメモリ表現を気にしない場合は、次の使用を検討してunionください。

template <typename T>
union Vec3
{
    T x, y, z;
    struct
    {
        T value[3];
    } vector;
};

ユニオンを使用すると、次のように各コンポーネントにアクセスするために配置を気にする必要はありません[]

Vec3<unsigned int> v3;

v3.vector.value[0] = 1;
v3.vector.value[1] = 2;
v3.vector.value[2] = 3;
于 2013-01-16T15:03:03.710 に答える