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

时间:2012-07-25 13:51:52

标签: c++ reference compiler-optimization

我正在制作一个涉及三维坐标的图书馆,并发现三维角度的成分有两个名称:偏航 - 俯仰 - 滚动和航向 - 高程 - 银行

所以我做了以下(在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 个答案:

答案 0 :(得分: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弥补了解除引用该指针的影响。

但是,我不担心,反而会关心风格。并且让两个成员对同一件事情进行说明......似乎错了。

答案 1 :(得分: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引用,因此可以通过这些方法实际修改struct的属性。例如:

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

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

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

我检查了GCC生成的汇编代码。直接使用struct属性(例如,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;

答案 2 :(得分: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)
 }