联盟正确用法

时间:2014-12-17 06:52:05

标签: c++ c++11

我对union的理解是它的所有值都分配在相同的内存地址中,并且内存空间与union的最大成员一样大。但我不明白我们将如何实际使用它们。 根据{{​​3}},这是一个使用联合的代码。

enum Type { str, num };

struct Entry {
     char* name;
     Type t;
     char* s;  // use s if t==str
     int i;    // use i if t==num
};

void f(Entry* p)
{
     if (p->t == str)
           cout << p->s;
     // ...
}

此后Bjarne说:

成员s和i永远不能同时使用,因此浪费了空间。通过指定两者都应该是union的成员,可以很容易地恢复它,如下所示:     联合价值{          char * s;          int i;     }; 该语言不会跟踪联合所持有的值,因此程序员必须这样做:     struct Entry {          char * name;          输入t;          价值v; //如果t == str,则使用v.s;如果t == num,请使用v.i.     };     void f(条目* p)     {          if(p-> t == str)                cout v.s;          // ...     }

任何人都可以进一步解释生成的联合代码吗?如果我们把它变成一个联盟,会发生什么?

3 个答案:

答案 0 :(得分:6)

假设你有一台32位机器,有32位整数和指针。您的结构可能如下所示:

[0-3] name
[4-7] type
[8-11] string
[12-15] integer

这是16个字节,但由于type(代码中为t)确定哪个字段有效,我们永远不需要实际存储string和{{1 }}字段同时。所以我们可以改变代码:

integer

现在的布局是:

struct Entry {
  char* name;
  Type t;
  union {
    char* s;  // use s if t==str
    int i;    // use i if t==num
  } u;
};

在C ++中,无论你最近分配的是&#34;有效的&#34;工会成员,但没有办法知道哪一个本质上,所以你必须自己存储它。这种技术通常被称为&#34;区分联盟&#34;,&#34;鉴别器&#34;是[0-3] name [4-7] type [8-11] string [8-11] integer 字段。

所以第二个结构需要12个字节而不是16个字节。如果您要存储大量的字节,或者它们来自网络或磁盘,您可能会关心这一点。否则,它并不重要。

答案 1 :(得分:2)

对于以下联盟,

union mix_types {
  int l;
  struct {
    short hi;
    short lo;
    } s;
  char c[4];
} mix;

内存结构如下: -

enter image description here

答案 2 :(得分:0)

使用联合的另一种方法是使用不同类型访问相同的数据。一个例子是DirectX矩阵结构,

typedef struct _D3DMATRIX {
    union {
        struct {
            float        _11, _12, _13, _14;
            float        _21, _22, _23, _24;
            float        _31, _32, _33, _34;
            float        _41, _42, _43, _44;

        };
        float m[4][4];
    };
} D3DMATRIX;

现在你可以做到,

D3DMATRIX d;
d._11 = 20;
// Now the value of m[0][0] is 20
assert(d._11 == m[0][0]);