我在页面中有以下列表:
#include "vector.h"
// An axis-aligned bounding box
class AABB
{
public:
VECTOR P; //position
VECTOR E; //x,y,z extents
AABB( const VECTOR& p, const VECTOR& e): P(p) ,E(e) {}
// ...
const SCALAR min( long i ) const
{
return ((AABB*)this)->P[i] - ((AABB*)this)->E[i];
}
// ...
};
现在我不明白的是,min()使用long值访问的是什么。
我已查看vector.h
并发现方括号运算符已超载:
class VECTOR
{
public:
SCALAR x,y,z; //x,y,z coordinates
//...
//index a component
//NOTE: returning a reference allows
//you to assign the indexed element
SCALAR& operator [] ( const long i )
{
return *((&x) + i);
}
//...
};
稍后用作:
// each axis
for( long i=0 ; i<3 ; i++ )
{
if( A.max(i)<B.min(i) && v[i]<0 )
{
那么为什么x
值引用会增加i
?
如果这个问题很荒谬,请耐心等待我,我还是个菜鸟。如果这还不够,我可以提供实际的来源
答案 0 :(得分:3)
它没有增加。
&x //<- address of member x
(&x) + i //<- address of member x shifted right by i SCALAR's
*((&x) + i) // the scalar value at that point
因此*((&x) + i)
返回第i个标量。 x代表0,y代表1,z代表2。
答案 1 :(得分:3)
这称为指针算法。
在代码中,&x
采用x
的地址作为指针;添加i
表示指针增加sizeof(x) * i
。通常,您可以实现与索引到数组相同的效果。例如,如果你有
int arr[10];
然后通过编写&arr[0] + i
有效地索引到数组中的i
整数。在某些情况下,可能会有一些其他类型的连续内存块而不是标准数组。
这不是所讨论的情况中发生的情况,因为这里没有数组或其他此类内存块。相反,代码假定编译器将计算VECTOR
的内存布局,以便将x
,y
和z
放在内存中,模拟数组布局。
然而,这种做法会根据C ++标准调用未定义的行为,因此VECTOR
的此实现存在缺陷,不应使用。
答案 2 :(得分:2)
在operator[]
中完成的操作是“指针算术” - 在这里使用普通的算术运算符(在这种情况下为+
)使用指针(通常使用数组)来导航内存。
您可以在此处查看此技术的更多示例: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html
应该注意的是,如果SCALAR
是一些非数组类型,那么我认为给出的代码是“危险的”,因为它假设{{1 },x
和y
将位于相邻的内存位置,这是标准C ++无法保证的。结果是,如果您尝试在不保证此假设的平台上使用此代码,那么z
最多会返回一些未定义的值,或者最坏情况会导致分段错误。
答案 3 :(得分:1)
那是指针算法。
在VECTOR
结构中,SCALAR
成员可能(无法保证。)连续出现在内存中,该代码的作者利用了只需在结构(x
)的第一个成员的内存地址中添加一个索引。
这是输入映射到输出的方式:
0
... *(&x + 0)
... x
1
... *(&x + 1)
... y
2
... *(&x + 2)
... z
然而,这是作者非常不安全的假设:V。
(填充字节,成员顺序等......)