我正在编写一个模板化的类,我有这样的东西:
template<class T> class ... {
T x, y, z;
T& operator[](int index) {
switch (index) {
case 0:
return this->x;
break;
case 1:
return this->y;
break;
case 2:
return this->z;
break;
}
}
}
我已经考虑过用这个来改变它:
T& operator[](int index) { return *(&this->x + index); }
然而,我在原始代码中返回的是实际变量(也称为引用),它执行它想要的操作(myObj[1] = 123; /*changes the actual object*/
),而在第二个示例中,我返回该指针的值。
我可以更改为return (&this->x + index)
来返回指针,但这两种情况都是编译的(Visual Studio 2013),我不知道该选择哪一种,因为我从未做过这样的事情。
那么,问题是:有没有什么方法可以使用指针算术来动态返回正确的变量,或者我需要切换?
指针算术方法会导致未定义的行为。例如,编译器可能会在这三个变量之间添加填充,这会使指针算术方法出现故障。它可能适用于某些类型的T
,而可能适用于另一种类型。
您要么需要使用切换方法,要么将您的成员从T x, y, z;
更改为T coords[3];
,这样您就可以使用具有定义和正确行为的索引方法。
关于您问题的主题,是的,将指针引用转换为引用通常是安全的。您将返回指向对象的引用。在这种情况下,它不是一个好方法的唯一原因是指针算术本身会导致未定义的行为。
所以,问题是:有什么方法可以使用指针算术来动态返回正确的变量,还是我需要切换?
实际上,你的指针运算会当场引发未定义的行为,因为添加了一些>1指向不指向数组对象的指针会导致未定义的行为,[expr.add]:
对于这些运算符,指向非数组对象的指针行为与指向的数组的第一个元素的指针相同length一,将对象的类型作为其元素类型。
当对具有整型的表达式进行加法运算或减法运算时从指针中,结果具有指针操作数的类型。[…]
如果指针操作数和结果都指向相同的元素数组对象,或数组对象最后一个元素之后的一个评估不得产生溢出;否则,行为为未定义。
您可以使用数组,并通过索引访问变量。请注意,switch
语句应该生成一个跳转表,不使用任何分支,甚至可能经过优化以生成与指针算法相同的代码。
尽管如此,如果您想向外部提供数组语义,您可能应该在内部保留一个数组。
除非x, y, z
保存在同一个容器中,否则我强烈避免执行第二个示例中的操作。即使从维护的角度来看,如果有人来了,决定重新安排你的成员或添加一个新成员(例如,在x
和y
之间),那么你的神奇记忆访问就完全混乱了。此外,如果使用3
作为参数调用函数,该怎么办?现在,你可以保证指向你不想指向的内存。
为了清晰、记忆安全和可持续性,请使用switch语句。此外,在return
之后,您不需要break
。。。这是个禁忌。最后,如果用户指定了负数或大于2的数字,则需要默认行为。抛出异常或以其他方式指示错误情况。