C++ 在这种情况下,运算符[]重载是如何工作的?

C++ 在这种情况下,运算符[]重载是如何工作的?,c++,overloading,C++,Overloading,我偶然发现了这门课: class Vec3f { ... float x, y, z; ... }; inline float operator[](const int index) const { return (&x)[index]; } inline float& operator[](const int index) { return (&x)[index]; } 该类使用[]访问数组中的x、y、z值,以便 v[0]

我偶然发现了这门课:

class Vec3f
{
    ...
    float x, y, z;
    ...
};

inline float operator[](const int index) const
{
    return (&x)[index];
}

inline float& operator[](const int index)
{
     return (&x)[index];
}
该类使用[]访问数组中的x、y、z值,以便 v[0]是x中的值,v[1]是y中的值,v[2]是z中的值,但是

return语句是如何工作的? 这样理解是否正确:从x的地址开始获取索引指定的地址中的值? Do&x必须在括号中,否则它将返回x[index]的地址值,不是吗?
从技术上讲,这是无效的代码

但是发生了什么:

// Declare four variables
// That are presumably placed in memory one after the other.
float x, y, z;
在守则中:

return (&x)[index];

// Here we take the address of x (thus we have a pointer to float).
// The operator [] when applied to fundamental types is equivalent to 
// *(pointer + index)

// So the above code is
return *(&x + index);
// This takes the address of x. Moves index floating point numbers further
// into the address space (which is illegal).
// Then returns a `lvalue referring to the object at that location`
// If this aligns with x/y/z (it is possible but not guaranteed by the standard)
// we have an `lvalue` referring to one of these objects.
很容易做到这一点并使其合法化:

class Vec3f
{
    float data[3];
    float& x;
    float& y;
    float& z;

    public:
        float& operator[](const int index) {return data[index];}

        Vec3f()
            : x(data[0])
            , y(data[1])
            , z(data[2])
        {}
        Vec3f(Vec3f const& copy)
            : x(data[0])
            , y(data[1])
            , z(data[2])
        {
            x = copy.x;
            y = copy.y;
            z = copy.z;
        }
        Vec3f& operator=(Vec3f const& rhs)
        {
            x = rhs.x;
            y = rhs.y;
            z = rhs.z;
            return *this;
        }
};

从技术上讲,这是无效的代码

但是发生了什么:

// Declare four variables
// That are presumably placed in memory one after the other.
float x, y, z;
在守则中:

return (&x)[index];

// Here we take the address of x (thus we have a pointer to float).
// The operator [] when applied to fundamental types is equivalent to 
// *(pointer + index)

// So the above code is
return *(&x + index);
// This takes the address of x. Moves index floating point numbers further
// into the address space (which is illegal).
// Then returns a `lvalue referring to the object at that location`
// If this aligns with x/y/z (it is possible but not guaranteed by the standard)
// we have an `lvalue` referring to one of these objects.
很容易做到这一点并使其合法化:

class Vec3f
{
    float data[3];
    float& x;
    float& y;
    float& z;

    public:
        float& operator[](const int index) {return data[index];}

        Vec3f()
            : x(data[0])
            , y(data[1])
            , z(data[2])
        {}
        Vec3f(Vec3f const& copy)
            : x(data[0])
            , y(data[1])
            , z(data[2])
        {
            x = copy.x;
            y = copy.y;
            z = copy.z;
        }
        Vec3f& operator=(Vec3f const& rhs)
        {
            x = rhs.x;
            y = rhs.y;
            z = rhs.z;
            return *this;
        }
};

此代码依赖于特定编译器的工作方式。从技术上讲,这是无效的代码。此代码取决于特定编译器的工作方式。从技术上讲,这是无效的代码。嗯,这是合法的,只是不正确,也就是说,它可能并不总是做正确的事情。是的,进一步的研究使我知道,这段代码严重依赖填充以保证其功能,是的,它可能是特定于编译器的,但是我在VS和GCC上测试了它,有/没有pragma packpush,1和pragma packpop成功了。我主要用C语言编程,所以我需要一个关于操作符重载的复习。为了完整起见,我会等待其他答案,但我同意你的看法。我想这是/合法的/只有在类不包含虚拟方法的情况下,代码片段没有显示它,但所述类上没有虚拟方法。从语法正确的角度来看,这是合法的。当索引==0或索引==1时,&x+索引部分需要工作以生成地址,但当索引!=0提供未定义的行为。从理论上讲,即使形成地址x+2也不需要工作,但实际上,它几乎肯定会在大多数实现中产生一个地址。@greyfade:其语法合法。但它在语义上是不合法的。它未定义的行为。是的,它是合法的,它只是不正确,也就是说,它可能并不总是做正确的事情。是的,进一步的研究使我知道这段代码严重依赖填充以保证其功能,是的,它可能是特定于编译器的,但是我在VS和GCC上测试了它,有/没有pragma packpush,1和pragma packpop成功了。我主要用C语言编程,所以我需要一个关于操作符重载的复习。为了完整起见,我会等待其他答案,但我同意你的看法。我想这是/合法的/只有在类不包含虚拟方法的情况下,代码片段没有显示它,但所述类上没有虚拟方法。从语法正确的角度来看,这是合法的。当索引==0或索引==1时,&x+索引部分需要工作以生成地址,但当索引!=0提供未定义的行为。从理论上讲,即使形成地址x+2也不需要工作,但实际上,它几乎肯定会在大多数实现中产生一个地址。@greyfade:其语法合法。但它在语义上是不合法的。它未定义的行为。