学习笔记:非受限联合体

来源:互联网 发布:打击电信网络诈骗 编辑:程序博客网 时间:2024/06/05 11:25
union Test {
    int i_;
    std::string s_;
};
int main()
{
    Test t;
    t.s = "abc";
    t.i = 100;
    return 0;
}
C++98中,上述代码无法编译通过。枚举中的std::string不是POD。
用反证法解释一下。
假设t.s="abc"编译成功,则t.i=100会直接破坏string中的指针数据。
C++11中,上述代码也无法编译通过。
但是原因是说,Test的默认构造,析构等函数都被打上了delete标志。
相当于 Test::Test() = delete ; ~Test::Test() = delete ;
直觉上,让int和string共享相同的存储空间好像能实现,只要小心处理一下即可。
我们只要重新定义Test的构造函数,析构函数,赋值函数等等......
这就是非受限联合体的由来,你可以混用std::string和int,只要不要胡来即可。
#include <iostream>
#include <string>
using namespace std;
union Test {
    enum class Tag { number, text } type;// discriminant
    int i_;
    std::string s_;
    Test& operator=(const Test& w);
    Test(int);
    Test(std::string);
    ~Test();
};
Test::Test(int i){
    type = Tag::number;
    i_ = i;
}
Test::Test(std::string s){
    type = Tag::text;
    new(&s_) std::string(s);
}
Test& Test::operator=(const Test& w)
{
    if (type==Tag::text && w.type==Tag::text) {
        s_ = w.s_;// usual string assignment
        return *this;
    }
    if (type==Tag::text) s_.~string();// destroy (explicitly!)
    switch (w.type) {
    case Tag::number:
        i_ = w.i_;
        break;
    case Tag::text:
        new(&s_) std::string(w.s_);
        break;// placement new
    }
    type = w.type;
    return *this;
}
Test::~Test()
{
    if (type==Tag::text){
        s_.~string();
    }
}
int main()
{
        Test  t1(100);
    cout << t1.i_ << endl;
    Test t2("abc");
    cout << t2.s_ << endl;
    t2 = t1;
    cout << t2.i_ << endl;
    return 0;
}
                                             
0 0
原创粉丝点击