我正在制作一个涉及三维坐标的图书馆,并发现三维角度的成分有两个名称:偏航 - 俯仰 - 滚动和航向 - 高程 - 银行
所以我做了以下(在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)
我想知道编译器是否会发现引用是不必要的,或者它是否会将指针保留在结构中。
此外,是否有更好的方法为一个成员拥有两个名字?
答案 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)
}