4. C++11非受限联合体

在C/C++中,联合体是一种构造类型的数据结构。在一个联合体内,我们可以定义多种不同的数据类型,这些数据类型共享相同的内存空间,可以达到节省内存空间的目的。

1. 取消数据类型的限制

在C++98中,针对联合体中的数据类型有一些限制,即联合体中不能有非POD类型,静态类型以及引用类型。

在C++11中,取消了对数据类型的限制,任何非引用类型都可以成为联合体的数据成员。

struct Student {
    Student(bool g, int a): gender(g), age(a) {}
    bool gender;
    int age;
};

union T {
    Student s;     //C++98编译失败,不是一个POD类型; C++11编译成功
    int id;
    char name[10];
};

2. 初始化

在C++98标准下,枚举类型中没有出现在初始化列表中的数据成员会被自动赋值,但这有时候会带来迷惑

union T {
    int s;
    double id;
    char name[5];
};
T t = {0};

上面代码中,用初始化列表的方式对枚举t赋初值0,试图将第一个成员变量s赋值为0,但实际上u所占的8字节空间会全部被赋值为0。

在C++11标准中,当联合体中有一个非POD的成员,并且该非POD成员有非平凡的构造函数,那么这个联合体的默认构造函数就会被编译器删除,同理,其他的特殊成员函数比如默认拷贝构造函数,拷贝赋值构造函数及析构函数,也遵循这个标准。

union T {
    string s;  // string 有非平凡的构造函数
    int n;
};

int main()
{
    T t;       // 构造失败,因为T 的默认构造函数被删除了
}

联合体T中的数据成员s有非平凡的构造函数,所以编译器会删除T的默认构造函数,因而t的构造就失败了。那么如何解决这种情况呢?办法是为联合体自定义一个构造函数:

union T {
    string s;  // string 有非平凡的构造函数
    int n;
public:
    // 自定义构造函数和析构函数
    T() { new (&s) string; }
    ~T() { s.~string(); }
};

int main()
{
    T t;       // 构造成功,定义了构造函数
}

猜你喜欢

转载自www.cnblogs.com/anlyse/p/10794985.html