13

没有办法做这样的事情,在 C++ 中有吗?

union {
    {
        Scalar x, y;
    }
    Scalar v[2];
};

哪里x == v[0]y == v[1]

4

8 回答 8

17

既然您使用的是 C++ 而不是 C,而且它们属于相同类型,为什么不直接将 xa 引用到 v[0] 并将 ya 引用到 v[1]

于 2009-03-31T19:30:09.763 回答
16

怎么样

union {
    struct {
        int x;
        int y;
    };
    int v[2];
};

编辑:

union a {
    struct b { int first, second; } bee;
    int v[2];
};

丑陋,但这样更准确

于 2009-03-31T19:29:47.517 回答
6

试试这个:

template<class T>
struct U1
{
    U1();
    T   v[2];
    T&  x;
    T&  y;
};

template<class T>
U1<T>::U1()
    :x(v[0])
    ,y(v[1])
{}

int main()
{
    U1<int>   data;

    data.x  = 1;
    data.y  = 2;
}
于 2009-03-31T20:57:30.927 回答
5

我以前用过这样的东西。我不确定它是否 100% 符合标准,但对于我需要使用它的任何编译器来说似乎都可以。

struct Vec2
{
  float x;
  float y;
  float& operator[](int i) { return *(&x+i); }
};

如果需要(您可能应该想要),您可以向 operator[] 添加边界检查等,并且您也可以提供 operator[] 的 const 版本。

如果您担心填充(并且不想添加适当的平台特定位来强制取消填充结构),那么您可以使用:

struct Vec2
{
  float x;
  float y;
  float& operator[](int i) {
    assert(i>=0);
    assert(i<2);
    return (i==0)?x:y;
  }
  const float& operator[](int i) const {
    assert(i>=0);
    assert(i<2);
    return (i==0)?x:y;
  }
};
于 2010-09-27T08:01:07.030 回答
2

我一直在寻找类似的东西,最终想出了一个解决方案。

我一直在寻找一个数据存储对象,我可以将其用作值数组和单个值(用于最终用户编写 Arduino 库的灵活性)。

这是我想出的:

class data{
    float _array[3];

    public:
    float& X = _array[0];
    float& Y = _array[1];
    float& Z = _array[2];

    float& operator[](int index){
        if (index >= 3) return _array[0]; //Make this action whatever you want...
        return _array[index];
    }
    float* operator&(){return _array;}
};


int main(){
    data Test_Vector;
    Test_Vector[0] = 1.23; Test_Vector[1] = 2.34; Test_Vector[2] = 3.45;

    cout<<"Member X = "<<Test_Vector.X;
    cout<<"Member Y = "<<Test_Vector.Y;
    cout<<"Member Z = "<<Test_Vector.Z;

    float* vector_array = &Test_Vector;

    cout<<"Array = {"<<vector_array[0]<<", "<<vector_array[1]<<", "<<vector_array[2]<<"}";
}

由于运算符重载,我们可以像使用数组一样使用数据对象,并且可以在函数调用中使用它来传递引用(就像数组一样)!

如果有更多 C++ 经验的人有更好的方法来应用这个最终产品,我很乐意看到它!

编辑:将代码更改为更加跨平台友好

于 2020-03-18T18:01:54.813 回答
2

鉴于你的例子:

union
{
    struct
    {
        Scalar x, y;
    };

    Scalar v[2];
};

正如其他人所指出的,一般来说,该标准不保证 x 和 y 之间没有填充,实际上编译器在结构中插入填充是非常常见的行为。

另一方面,使用以下解决方案:

struct U
{
    int   v[2];
    int&  x;
    int&  y;
};

U::U()
    : x(v[0])
    , y(v[1])
{}

我不喜欢的主要是我不得不提到 x, y两次。对于我有不止几个元素(比如 10 个)的情况,这变得更不可读并且更难维护 - 例如,如果你想更改 x,y 的顺序,那么你也必须更改下面的索引(当然不是强制性的,但内存中的顺序与字段顺序不匹配,不建议这样做)。此外,U 不能再是POD,因为它需要用户定义的构造函数。最后,x & y 引用会消耗额外的内存。

因此,我提出的(我可以接受的)折衷方案是:

struct Point
{
    enum CoordType
    {
        X,
        Y,
        COUNT
    };

    int coords[CoordType::COUNT];
};

typedef Point::CoordType PtCoord;

有了这个,你可以这样做:

Point p;
for ( int i = 0; i < PtCoord::COUNT; i++ )
    p.coords[i] = 100;
std::cout << p.coords[PtCoord::X] << " " << p.coords[PtCoord::Y] << std::endl;

// 100 100

有点复杂,但我更喜欢这个而不是参考建议。

于 2020-04-29T19:12:06.280 回答
1

根据“标量”是什么,是的,您可以在 C++ 中做到这一点。语法几乎与您在示例中所写的完全一致(甚至可能完全正确,但我对联合感到生疏)。它与 C 相同,除了对可以在联合中的类型有限制(IIRC 它们必须具有默认构造函数)。这是相关的维基百科文章

于 2009-03-31T19:29:39.437 回答
1

使用 C++11,你有匿名联合和结构,它们只是将它们的定义导出到封闭范围,所以你可以这样做:

typedef int Scalar;
struct Vector
{
    union
    {
        struct
        {
            Scalar x, y;
        };
        Scalar v[2];
    };
};
于 2020-12-01T15:38:48.033 回答