[C++ primer]联合:节省空间的类

联合是一种特殊的类。一个 union 对象可以有多个数据成员,但在任何时刻,只有一个成员可以有值。当将一个值赋给 union 对象的一个成员的时候,其他所有都变为未定义的。
为 union 对象分配的存储的量至少与包含其最大数据成员的一样多。像任何类一样,一个 union 定义了一个新的类型。

1、定义联合

联合提供了便利的办法表示一组相互排斥的值,这些值可以是不同类型的。

// objects of type TokenValue have a single member,
// which could be of any of the listed types
union TokenValue {
    char cval;
    int ival;
    double dval;
};//sizeof(TokenValue)=sizeof(double)

每个 union 对象的大小在编译时固定的:它至少与 union 的最大数据成员一样大。

2、没有静态数据成员、引用成员或类数据成员

(联合里面的东西共享内存,所以静态、引用都不能用,因为他们不可能共享内存。)

某些(但不是全部)类特征同样适用于 union。例如,像任何类一样,union可以指定保护标记使成员成为公用的、私有的或受保护的。默认情况下,union 表现得像 struct:除非另外指定,否则 union 的成员都为 public 成员。

union 也可以定义成员函数,包括构造函数和析构函数。但是,union 不能作为基类使用,所以成员函数不能为虚数。
union 不能具有静态数据成员或引用成员,而且,union 不能具有定义了构造函数、析构函数或赋值操作符的类类型的成员:

union illegal_members {
    Screen s;           // error: has constructor
    static int is;      // error: static member
    int &rfi;           // error: reference member
    Screen *ps;         // ok: ordinary built-in pointer type
};

这个限制包括了具有带构造函数、析构函数或赋值操作符的成员的类。

3、使用联合类型
union 的名字是一个类型名:

TokenValue first_token = {‘a‘};   // initialized TokenValue
TokenValue last_token;            // uninitialized TokenValue object
TokenValue *pt = new TokenValue;  // pointer to a TokenValue object

像其他内置类型一样,默认情况下 union 对象是未初始化的。可以用与显式初始化简单类对象一样的方法显式初始化 union 对象。但是,只能为第一个成员提供初始化式。该初始化式必须括在一对花括号中。first_token 的初始化给它的 cval 成员一个值。

4、使用联合的成员
可以使用普通成员访问操作符(. 和 ->)访问 union 类型对象的成员:
last_token.cval = ‘z‘;
pt->ival = 42;
给 union 对象的某个数据成员一个值使得其他数据成员变为未定义的。使用 union 对象时,我们必须总是知道 union 对象中当前存储的是什么类型的值。通过错误的数据成员检索保存在 union 对象中的值,可能会导致程序崩溃或者其他不正确的程序行为。

注:避免通过错误成员访问 union 值的最佳办法是,定义一个单独的对象跟踪 union 中存储了什么值。这个附加对象称为 union 的判别式。

5、嵌套联合
union 最经常用作嵌套类型,其中判别式是外围类的一个成员:

class Token {
public:
    // indicates which kind of value is in val
    enum TokenKind {INT, CHAR, DBL};
    TokenKind tok;
    union {           // unnamed union
    char cval;
    int ival;
    double dval;
    } val;            // member val is a union of the 3 listed types
};

这个类中,用枚举对象 tok 指出 val 成员中存储了哪种值,val 成员是一个(未命名的)union,它保存 char、int 或 double 值。
经常使用 switch 语句测试判别式,然后根据 union 中当前存储的值进行处理:

Token token;
switch (token.tok) {
case Token::INT:
    token.val.ival = 42; break;
case Token::CHAR:
    token.val.cval = ‘a‘; break;
case Token::DBL:
    token.val.dval = 3.14; break;
}

6、匿名联合

不用于定义对象的未命名 union 称为匿名联合。匿名 union 的成员的名字出现在外围作用域中。例如,使用匿名 union 重写的 Token 类如下:

class Token {
public:
    // indicates which kind of token value is in val
    enum TokenKind {INT, CHAR, DBL};
    TokenKind tok;
    union {              // anonymous union
        char cval;
        int ival;
        double dval;
    };
};

因为匿名 union 不提供访问其成员的途径,所以将成员作为定义匿名union 的作用域的一部分直接访问。重写前面的 switch 以便使用类的匿名union 版本,如下:

Token token;
switch (token.tok) {
case Token::INT:
    token.ival = 42; break;
case Token::CHAR:
    token.cval = ‘a‘; break;
case Token::DBL:
    token.dval = 3.14; break;
}

注:匿名 union 不能有私有成员或受保护成员,也不能定义成员函数。

原文:C++primer(第四版)18.5节

时间: 2024-11-03 21:32:33

[C++ primer]联合:节省空间的类的相关文章

C++ Primer 学习笔记_105_特殊工具与技术 --联合:节省空间的类

特殊工具与技术 --联合:节省空间的类 联合是一种特殊的类.一个 union 对象可以有多个数据成员,但在任何时刻,只有一个成员可以有值.当将一个值赋给 union 对象的一个成员的时候,其他所有都变为未定义的. 为 union 对象分配的存储的量至少与包含其最大数据成员的一样多.联合提供了便利的办法表示一组相互排斥的值,这些值可以是不同类型的. 1.定义联合 作为例子,我们可能有一个处理不同各类数值或字符数据的过程.该过程可以定义一个 union 来保存这些值: union ToKenValu

第二十章 内存等空间管理类的实现

                   第二十章   内存等空间管理类的实现      空间.时间对我来说,或许永远是一个迷.即使我曾经深入到原子的最深处,即使人类科学家是自欺欺人,即使我了解到的最深层次的部分真理是正确的:那又能怎样?那都是过去式,在那光明与黑暗一体之地.我的灵魂受伤了:我不得不回到电脑这块充满垃圾的地方修心养性. 或许我的论述方法不好,要完全理解本章是有点难度:你要对简单的空间概念需要一定的理解,即使只是论述1D的线性平面空间中的2个基本方法:分配与释放,但也很复杂.要知道LI

七牛云上传视频如何有效做到节省空间

在上传视频的时候,我们通常会保存到第三方[七牛云]平台.不过大多数程序员在系统后台上传视频后,一般都是保存到了本地,如果视频非常多或者视频容量特别大的情况下,那么我们的服务器迟早有一天会满,为了节省空间,下面教大家再上传视频时,如何以有效的节省服务器空间,一般情况下会把这些文件存到第三方,也就是需要我们下载qiniusdk,把qiniusdk放如Vendor目录下. 这里我们以课程视频为例子,实现的hmtl源代码如下:<tr> <td class="text">

windows系统做了压缩文件以节省空间之后,sqlserver服务无法启动

首先查看日志文件:发现有两个严重错误. 2014-07-27 22:28:32.81 spid7s      Starting up database 'master'. 2014-07-27 22:28:32.90 spid7s      错误: 5118,严重性: 16,状态: 1. 2014-07-27 22:28:32.90 spid7s      文件 "C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DA

【足迹C++primer】54、继承类的范围,构造函数和拷贝控制

继承类的范围,构造函数和拷贝控制 当用派生类执行函数的时候,首先会在当前的类里面找 如果找不到就一级一级地往上找. Name Lookup Happens at Compile Time class Quote { public: Quote()=default; Quote(const string &book, double sales_price):bookNo(book), price(sales_price) {cout<<"Quote gouzhao functi

BitMap排序-大数据量节省空间

package com.jp.algorithm.sort; /** * 假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复).那么我们就可以采用Bit-map的方法来达到排序的目的.要表示8个数 * ,我们就只需要8个Bit(1Bytes),首先我们开辟1Byte的空间,将这些空间的所有Bit位都置为0 * 然后遍历这5个元素,首先第一个元素是4,那么就把4对应的位置为1. * 然后再处理第二个元素7,将第八位置为1,,接着再处理第三个元素,一直到最后处理完所有

【足迹C++ primer】11、返回类型和return语句(1)

返回类型和return语句 1.返回数组指针 由于数组不能被拷贝,所以函数不能返回数组. 但是函数可以返回数组的指针或引用. typedef int arrT[10]; using arrT=int[10];<span style="white-space:pre"> </span>//arrT的等价声明 arrT* func(int i);<span style="white-space:pre"> </span>/

Redis节省空间

节省空间 使用较短的键名 内部编码的优化.每种类型可以使用不同的数据结构来实现,通过配置文件可以配置在某些条件来触发使用不同的数据结构. 如果发现错误,请轻拍,欢迎留言交流,谢谢

一种节省空间的交换变量的基本算法

一种节省空间的交换变量的基本算法,一个很简单的算法 因为其中没有引入temp变量,所以可以节省空间 代码如下: 一种节省空间的交换变量的基本算法