5

私は 3 次元座標を含むライブラリを作成していますが、3 次元角度のコンポーネントにはヨー ピッチ ロールとヘディング エレベーション バンクの 2 つの名前があることを発見しました。

だから私は次のようにしました(c ++ 11で行いました):

struct Angle {
    float heading;
    float elevation;
    float bank;
    float &yaw = heading;
    float &pitch = elevation;
    float &roll = bank;

     // Some Constructors (copy and assignment have to be made manually)
 }

これには、2 つの名前スキーム間で表記法を同等に保つという利点があります。例えば:

Angle angle;
rotate(angle.yaw); // this is equivalent to rotate(angle.heading)

コンパイラーが参照が不要であると判断するのか、それともポインターを構造体に保持するのか疑問に思っていました。

また、1人のメンバーに2つの名前を持つより良い方法はありますか?

4

3 に答える 3

2

コンパイラーが参照が不要であると判断するのか、それともポインターを構造体に保持するのか疑問に思っていました。

99.9% の場合、ポインターは構造体に保持されます。コンパイラが翻訳単位でそれらを除外する方法がわかりません。特に、構文が無効であるため、コンストラクターで参照を初期化する必要がありますが、これは非常に隠されている可能性があります。そのため、どの参照がどのメンバーを参照しているかを知る方法はありません。

パフォーマンスのオーバーヘッドも発生する可能性があります。例えば:

  float x = a.elevation;
013F13E0  fld         dword ptr [ebp-18h] 
013F13E3  fstp        dword ptr [x] 
  float y = a.pitch;
013F13E6  mov         eax,dword ptr [ebp-0Ch] 
013F13E9  fld         dword ptr [eax] 
013F13EB  fstp        dword ptr [y] 

実際、内部的には、参照はポインターのように機能します。したがって、余分なmovものはそのポインターの逆参照を補います。

私はそれについて心配しませんが、代わりにスタイルを気にします. そして、同じことを説明する2人のメンバーを持つことは...間違っているようです。

于 2012-07-25T14:08:46.757 に答える
1

私は2つの異なるオプションを考えることができます。最初のものは、@ Nealがすでに提案しているものとほぼ同じですが、実際のC++コードが含まれています。

struct Angle {
    float heading;
    float elevation;
    float bank;

    float& yaw() { return heading; }
    float& pitch() { return elevation; }
    float& roll() { return bank; }

    const float& yaw() const { return heading; }
    const float& pitch() const { return elevation; }
    const float& roll() const { return bank; }
};

最初のメソッドセットは非定数参照を返すため、これらのメソッドを使用して構造体の属性を実際に変更することができます。例えば:

Angle a{60, 45, 0};
a.roll() = 15;

2番目のセットは、Angleへの定数参照があり、構造体の値を読み取りたい場合に使用されます。例えば:

void print_yaw(const Angle& a) {
    std::cout << "yaw=" << a.yaw() << std::endl;
}

GCCで生成されたアセンブリコードを確認しました。構造体属性(eg、a.heading)を直接使用する場合とエイリアスメソッド(eg、a.yaw())を使用する場合の両方で同じアセンブリコードが生成されるため、エイリアスメソッドを使用してもペナルティは発生しません。

私が考えることができる2番目の方法は、まったく異なるアプローチを使用することです。このようなもの:

enum Accessors { HEADING=0, ELEVATION, BANK };
enum AliasedAccessors { YAW=0, PITCH, ROLL };
typedef float Angle[3];

Angle a{60, 45, 0};
std::cout << a[HEADING] << " must be equal to " << a[YAW] << std::endl;
于 2012-07-25T15:17:20.073 に答える
0

なぜこれほど多くのパブリック変数を作成するのですか?

いくつかのゲッターとセッター(擬似コード)を作成できます。

struct Angle {
    float heading;
    float elevation;
    float bank;

    float& yaw() const  {
         return heading;
    }
    float& pitch() const  {
         return elevation;
    }
    float& roll() const  {
         return bank;
    }

    //etc...

    // Some Constructors (copy and assignment have to be made manually)
 }
于 2012-07-25T13:55:56.993 に答える