类引用成员指向同一类中的其他成员

5

我正在制作一个涉及3D坐标的库,发现有两种称为3D角度组件的名称:偏航-俯仰-翻滚和方位-高程-滚转。

因此,我编写了以下代码(使用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)

我在想编译器是否会发现这些引用是不必要的,还是它会保留结构中的指针。

此外,有没有更好的方法为一个成员拥有两个名称?

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补偿了解除引用指针的操作。

我不会太担心这个问题,相反我更关注代码风格。而且有两个成员变量表示同一件事情...似乎是错误的。


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; }
};

第一组方法返回非const引用,因此可以通过这些方法实际修改结构体的属性。例如:

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;

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)
 }

我基本上写了同样的东西 :) 但是,你不应该返回实际属性的引用吗?否则,它们无法通过替代名称进行修改。实际上,应该提供两组方法:const float& yaw() const;float& yaw();。然后它也可以与对常量 Angle 的引用一起使用。 - betabandido
@betabandido 把我的代码改掉吧 ^_^ 就像我说的那样,这只是“伪代码”。显然它不会完全像这样 ^_^(顺便说一下,我确实返回引用 :-P) - Naftali
@LuchianGrigore 啊!伪代码 伪代码 伪代码. - Naftali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接