在结构中重载运算符() C++
C++ overloading operator() in struct
这是来自Box2d物理引擎的b2Math.h的代码。
struct b2Vec2
{ ...
/// Read from and indexed element.
float operator () (int i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float operator () (int i)
{
return (&x)[i];
}
...
float x, y;
}
为什么我们不能只使用 SomeVector.x 和 SomeVector.y 来读/写矢量坐标?return (&x)[i];
行实际上是如何工作的?我的意思是,在引用结构的 x 组件之后的数组制动器 [] 对我来说并不清楚。
提前感谢您的回复。
这是来自Box2d物理引擎的b2Math.h的代码。
您发布的 Box2D 源代码的复制和粘贴中似乎存在错误。特别是,在非常量方法中似乎缺少与号。
此外,此代码片段似乎来自当前发布的 2.3.2 代码库以外的代码库。
以下是GitHub上Box2D 2.3.2源代码的部分:
/// Read from and indexed element.
float32 operator () (int32 i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float32& operator () (int32 i)
{
return (&x)[i];
}
为什么我们不能只使用 SomeVector.x 和 SomeVector.y 来读/写矢量坐标?
我们可以,而且我们通常这样做。
然而,Box2D(特别是b2AABB::RayCast
)中的一些代码似乎是从算法编写的(b2AABB::RayCast
的注释说"来自实时碰撞检测,p179"),该算法迭代x和y作为数组下标零和一。我猜Erin Cato(Box2D的作者)是这样实现这些运算符的:(a)使访问在风格上更符合算法,(b)使其工作,(c)使其以看起来有效的方式工作。我可以确认它至少有效。
我有自己的 Box2D 分支,其中我重写了这些运算符。我将其接口更改为使用[]
(而不是()
),并将其实现更改为使用switch
语句显式访问x
或y
。后者我这样做是为了清楚地避免潜在的未定义行为,w.r.t. C++标准。
以下是我的实现的相关部分的片段(请注意,我甚至不声称这是完美的或好的,只是说它是一个有效的替代实现,并且它显然应该依赖于定义的行为):
/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto operator[] (size_type i) const
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}
/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto& operator[] (size_type i)
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}
行返回 (&x)[i]; 实际上是如何工作的?
正如我上面所暗示的,我之前已经研究过这个确切的问题。
当结构的 x 和 y 成员变量的内存布局与具有两个浮点数的数组相同时,它就会起作用;它通常这样做。所以与号 (&
) 获取x
参数的地址,然后将该地址视为数组开头的地址,然后按i
进行索引。
我不认为这是定义的行为,但就C++标准而言。然而,对于我的口味来说,它的定义还不够明确。
希望这能回答你的问题。
- 为什么比较运算符如此快速
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 增量运算符与后缀混淆
- 一个关于在C++中重载布尔运算符的问题
- 运算符C++ "delete []"仅删除 2 个前值
- 模板类无法识别友元运算符
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 关闭||运算符优化
- 通过继承类使用来自不同命名空间的运算符
- C++Cast运算符过载
- 如何使用AngelScript注册SFML Vector2运算符
- 重载元组索引运算符-C++
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 布尔比较运算符是如何在C++中工作的
- 重载运算符new[]的行为取决于析构函数
- 如何防止clang格式在流运算符调用之间添加换行符<<