工会积极成员背后的理由 [英] Rationale behind active members of unions

查看:23
本文介绍了工会积极成员背后的理由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C++ 的联合比 C 的联合更具限制性,因为它们引入了活动成员"(最后分配给的成员)的概念,作为唯一可以安全访问的成员.在我看来,工会的这种行为是消极的.有人可以解释一下这个限制有什么好处吗?

C++'s unions are more restrictive than those of C, because they introduce the concept of an "active member" (the one last assigned to) as the only one safe to access. The way I see it, this behavior of unions is a net negative. Can someone please explain what is gained by having this restriction?

推荐答案

简短回答

在 C 中,联合只是一个关于如何解释存储在给定位置的数据的问题.数据是被动的.

Short answer

In C, the union is only a question of how to interpret the data that is stored at a given location. The data is passive.

在 C++ 中,联合可以有不同类的成员.而类对象不仅有数据,还有行为.由于您依赖于这种(可访问的)行为(甚至可能无法访问私有成员和受保护成员),因此必须确保对象从构造到销毁始终保持一致.活动成员的概念正是为了这个目的:确保对象生命周期是一致的.

In C++, unions can have members of different classes. And class objects do not only have data, but also have a behavior. As you rely on this (accessible) behavior (and maybe can't even access the private and protected members), it must be ensured that the object remain consistent from its construction to its destruction. The notion of active member is there exactly for this purpose: ensure that the object lifecycle is consistent.

想象以下联合:

union U {
    string s;
    int i;

    // due to string, I need to define constructor and destructor
    U (string s) : s(s) { cout << "s is active"<<endl;}
    U (int i) : i(i) { cout << "i is active"<<endl;}
    U() : s() { cout << "s is active by default" <<endl; }
    ~U() { cout << "delete... but what ?"<<endl; }
};

现在假设我初始化它:

U u("hello"); 

此时的活跃成员是s.我现在可以毫无风险地使用这个活跃的成员:

The active member is s at that moment. I can now use this active memeber without risk:

u.s += ", world";  
cout << u.s <<endl;

在更改活动成员之前,我必须确保成员的生命周期结束(按照 C++ 标准的要求).如果我忘记了这一点,例如使用另一个成员:

Before changing the active member, I have to be sure that the lifetime of the member is ended (requirement as per C++ standard). If I forget this, and for example use another member:

u.i=0;  // ouch!!! this is not the active member : what happens to the string ?  

然后我有未定义的行为(实际上,s 现在已损坏,无法再恢复存储字符的内存).你也可以想象相反的情况.假设活动成员是 i,我现在想使用字符串:

I have then undefined behavior (in practice here, s is now corrupted and it is no longer possible to recover the memory in which the characters were stored). You could also imagine the opposite. Suppose the active member would be i, and I want now to use the string:

u.s="goodbye";  // thinks that s is an active valid string which is no longer the case 

在这里,编译器假设我知道 s 是活动成员.但由于 s 不是一个正确初始化的字符串,执行复制运算符也会导致未定义的行为.

Here, the compiler assulmes that I know that s is the active member. But as s is not a properly initializeed string, performing a copy operator will also result in undefined behavior.

演示您不应该做的事情

标准解释:

如果 M 有一个非平凡的析构函数,而 N 有一个非平凡的构造函数(例如,如果他们声明或继承虚函数),u 的活跃成员可以安全地从 m 切换到 n 使用析构函数和放置新表达式如下:

If M has a non-trivial destructor and N has a non-trivial constructor (for instance, if they declare or inherit virtual functions), the active member of u can be safely switched from m to n using the destructor and placement new-expression as follows:

u.m.~M();
new (&u.n) N;

所以在我们讨厌的例子中,下面的方法是可行的:

So in our nasty example, the following would work:

u.s.~string(); // properly end the life of s
u.i=0;  // this is now the active member   
           // no need to end life of an int, as it has a trivial destructor 
new (&u.s) string("goodbye");  // placement new  
cout << u.s <<endl;    

演示如何(几乎)正确操作

这篇关于工会积极成员背后的理由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆