5

我正在制作一个涉及 3-D 坐标的库,并发现 3-D 角度的组件有两个名称:yaw-pitch-roll 和 heading-elevation-bank

所以我做了以下(在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)
 }

这样做的好处是在两个名称方案之间保持符号等效。例如:

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

我想知道编译器是否会发现引用是不必要的,或者是否会将指针保留在结构中。

另外,有没有更好的方法让一个成员有两个名字?

4

3 回答 3

2

我想知道编译器是否会发现引用是不必要的,或者是否会将指针保留在结构中。

在 99.9% 的情况下,指针将保留在结构中。我看不到编译器可以通过翻译单元将它们排除在外。Esp,因为您的语法无效,并且您必须初始化构造函数中的引用,这很可能被隐藏。所以它没有办法知道哪个参考引用了哪个成员。

也可能有一些性能开销。例如:

  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弥补了取消引用该指针。

不过我不会担心它,而是会关心风格。让两个成员负责同一件事……似乎是错误的。

于 2012-07-25T14:08:46.757 回答
1

我可以想到两种不同的选择。第一个几乎是@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;

当你有一个对角度的常量引用并且你只想读取结构中的值时,使用第二组。例如:

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

我检查了 GCC 生成的汇编代码。直接使用结构属性(例如,a.heading)和使用别名方法(例如,a.yaw())都会生成相同的汇编代码,因此您无需为使用别名方法付出任何代价。

我能想到的第二种方法是使用完全不同的方法。像这样的东西:

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

为什么要制作这么多公共变量?

你可以只做一些getter和setter(伪代码):

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 回答