【问题标题】:C++ overloading operator() in struct结构中的 C++ 重载 operator()
【发布时间】:2017-04-13 17:23:33
【问题描述】:

这是来自 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 组件的引用之后的数组刹车 [] 对我来说并不清楚。

提前感谢您的回复。

【问题讨论】:

  • "为什么我们不能只使用 SomeVector.x 和 SomeVector.y 来读取/写入矢量坐标?"你如何声明SomeVector?这不在您的代码示例中。
  • (&x)[i] 对除0 之外的任何i 表现出未定义的行为,因为它将尝试在未分配给此类数组的内存中执行数组索引。
  • 修改operator()时出错:应该返回float&
  • 您似乎缺少重要信息来完全回答问题。但是,“为什么我们不能只使用 SomeVector.x 和 SomeVector.y 来读取/写入矢量坐标?”很简单,你可以:)
  • @CoryKramer 我很确定在大多数实现中xy 在内存中是相邻的。这不能保证吗? (注意我不是 OP。)

标签: c++ struct operator-overloading box2d


【解决方案1】:

这是来自 Box2d 物理引擎的 b2Math.h 的代码。

您发布的 Box2D 源代码的复制和粘贴似乎有错误。特别是,在非常量方法中似乎缺少 & 符号。

此外,此代码 sn-p 似乎来自一个代码库,而不是当前发布的 2.3.2 代码。

这是来自Box2D 2.3.2 sources on GitHub的部分:

/// 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)似乎是由迭代 x 和 y 的算法(b2AABB::RayCast 的注释说“来自实时碰撞检测,p179”)编写的作为数组下标零和一。我猜 Erin Cato(Box2D 的作者)以这种方式实现了这些运算符:(a)使访问在风格上更符合算法,(b)使其工作,以及(c)使其工作在 a看起来有效的方式。我可以确认它至少可以工作。

我有my own fork of Box2D,我在其中重写了这些运算符。我将其接口更改为使用[](而不是()),并将其实现更改为使用switch 语句来显式访问xy。我这样做是为了清楚地避免潜在的未定义行为 w.r.t. C++ 标准。

这是我的实现的相关部分的sn-p(请注意,我并不认为这是完美或好的,只是它是一种替代实现有效,并且它显然应该依赖于定义的行为):

/// 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 成员变量的内存布局与具有两个浮点数的数组相同时有效;它通常会这样做。因此,& 符号 (&amp;) 获取 x 参数的地址,然后将该地址视为数组开头的地址,然后按 i 索引。

我不认为这是定义的行为,但就 C++ 标准而言。然而,它的定义不够明确,不符合我的口味。

希望这能回答您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    相关资源
    最近更新 更多