【问题标题】:How does this implementation of operator[] function work?这个 operator[] 函数的实现是如何工作的?
【发布时间】:2017-12-30 05:21:43
【问题描述】:

我正在阅读一本书(Eric Lengyel 的游戏引擎开发基础),这本书正在用 c++ 编写一些向量操作,这里是 sn-p:

struct Vector3D
{
    float x, y, z;

    Vector3D() = default;

    Vector3D(float a, float b, float c)
    {
        x = a;
        y = b;
        z = c;
    }

    float& operator [](int i)
    {
        return((&x)[i]);
    }
};

我特别关心这件作品:

float& operator [](int i)
{
    return((&x)[i]);
}

现在,无论输入什么索引,我都希望这段代码返回 x。但是,根据输入输出相应的变量(x、y 或 z)。为什么是这样?感谢您的帮助。

【问题讨论】:

  • 这是在滥用undefined behavior(解除对越界指针的引用),因为它知道编译器如何将成员放入对象中的特定于实现的布局。如果你的书推荐了类似的东西,那么你应该把它扔掉!
  • 按照@Someprogrammerdude 所说的,我想补充一点,它是最糟糕的未定义行为之一,未定义行为将在 99.9% 的时间内起作用(因为很少有编译器会重新排列或在这些浮动之间放置填充)。如果/当它确实崩溃时,将很难追踪。
  • @Someprogrammerdude 这本书并没有特别推荐它,但建议这是 3d 矢量的简单 c++ 表示。将开关与 case 0:return &x、case 1:return &y 等一起使用会更好吗?
  • @JoeGuida,只定义一个三元素数组会更容易,或者最好使用std::array<float, 3>
  • @AndyG,谢谢,我可以直接访问元素,例如:v.x、v.y、v.z。我只是想知道那个操作员是如何工作的。他在这里做了一个类似的 Vector3D& operator *= (float s) { x *= s; y *= s; z *= s;返回(*这个); }

标签: c++ vector 3d game-engine


【解决方案1】:

暂时,让我们忽略函数实现方式的恶臭。

问题是,它是如何工作的?

如果查看类的一个对象的成员变量,当成员之间没有填充时,它们在内存中的布局为:

+-----+-----+-----+
|  x  |  y  |  z  |
+-----+-----+-----+

使用这样的布局,对象看起来好像是floats 的数组。

如果你使用:

float* ptr = &x;

ptr 指向此类数组的第一个元素。

ptr[0] 计算为数组的第一个元素,与x 相同。
ptr[1] 计算为数组的第二个元素,与y 相同。
ptr[2] 计算为数组的第三个元素,与z 相同。

这就是为什么

return((&x)[i]);

大部分时间都可以工作,即使这样的代码会导致标准中未定义的行为。

【讨论】:

  • 如果您知道您的编译器做了什么,无论是因为它记录了它还是因为您细致地测试,您都可以这样做。只是不要忘记在每次更改编译器或编译器选项时重复测试。
猜你喜欢
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-17
  • 2016-02-22
  • 1970-01-01
相关资源
最近更新 更多