Chapter 19: Structs and Unions

结构

C++中的结构等同于类,所不同的是结构的成员默认为public访问级别,而不是类中的private访问级别。通常,结构用来替换类来表示主要包含公开域的简单数据结构。

struct Point
{
    int x, y; // public
};
class Point
{
    int x, y; // private
};

结构初始化

要声明结构的对象,你使用通常的声明语法。

Point p, q; // object declarations

另一种使用结构(与类)的语法是在定义结构时将对象名放置在最后的冒号之后。此位置被称为声明器列表,并且包含逗号分隔的声明器序列。

struct Point
{
    int x, y;
} r, s; // object declarations

当使用对象初始化时,结构的名字可以省略。这被称为匿名结构。

struct
{
    int x, y;
} r, s;

聚合初始化也通常用于结构,因为这种语法缩写仅适用于聚合类型:数组,类,结构与联合。要使得初始化正常工作,类型不能包含任何私有与受保护的非静态域。

int main()
{
    // Aggregate initialization
    Point p = { 2, 3 };
}

对于支持C++11或以后版本的编译器,更推荐统一初始化语法,因为它移除了聚合类型与非聚合类型的初始化之间的区别。

int main()
{
    // Uniform initialization
    Point q { 2, 3 };
}

联合

尽管类似于结构,联合类型的不同点在于所有域共享相同的内存位置。所以,联合的尺寸是它所包含的最大域的尺寸。例如,在下面的示例中,其尺寸为整型域的尺寸,为四个字节大小。

union Mix
{
    char c; // 1 byte
    short s; // 2 bytes
    int i; // 4 bytes
} m;

这意味着联合类型一次仅存储一个值,因为修改一个域会覆盖其它的值。

int main()
{
    m.c = 0xFF; // set first 8 bits
    m.s = 0; // reset first 16 bits
}

除了节省内存使用以外,联合的优点在于它提供了查看相同内存位置的多种方法。例如,下面的联合有三个数据成员,允许以多种方式访问相同的四个字节组合。

union Mix
{
    char c[4]; // 4 bytes
    struct { short hi, lo; } s; // 4 bytes
    int i; // 4 bytes
} m;

整型域一次访问四个字节。使用此结构,可以一次查看两个字节,而通过使用char数组,可以单独访问每个字节。

int main()
{
    // Set i = 11111111 00000000 11110000 00001111
    m.i=0xFF00F00F;
    m.s.lo; // 11111111 00000000
    m.s.hi; // 11110000 00001111
    m.c[3]; // 11111111
    m.c[2]; // 00000000
    m.c[1]; // 11110000
    m.c[0]; // 00001111
}

匿名联合

联合的声明可以无需类型名或对象名。这被称为匿名联合,并且定义在了一个可以在其声明作用域内直接访问的成员。不同于普通的联合,匿名联合不能包含方法或非公开成员。

int main()
{
    union { short s; }; // defines an unnamed union object
    s = 15;
}

全局声明的匿名联合必须为静态。

static union {};