只与一个成员一起使用联合的目的是什么?


89

当我阅读seastar源代码时,我注意到有一个称为tx_side只有一个成员的联合结构。这是解决某些问题的技巧吗?

仅供参考,我将tx_side以下结构粘贴:

union tx_side {
    tx_side() {}
    ~tx_side() {}
    void init() { new (&a) aa; }
    struct aa {
        std::deque<work_item*> pending_fifo;
    } a;
} _tx;


5
@MaxLanghof这个问题和相应的答案没有提到使用这种联合结构的目的。
daoliker

您有使用此成员的示例吗?
n314159

4
这就是为什么我实际上没有使用我的有约束力的关闭投票的原因。但是我不确定您对问题的答案到底期望什么,而不是直接从那里得到的答案。假定使用union代替的目的struct是两者之间的一个或多个差异。这是一种非常晦涩的技术,因此除非该代码的原始作者出现,否则我不确定有人可以给您一个权威性的答案,他们希望以此解决这个问题(如果有)。
Max Langhof

2
我最好的猜测是,union用于延迟构造(在这种情况下没有意义)或防止未决的_fifo破坏(导致内存泄漏)。但是没有用法的例子很难说。
康斯坦丁·史蒂普尼克'19

Answers:


82

因为tx_side是联合,tx_side()所以不会自动初始化/构造a~tx_side()也不会自动对其进行破坏。这样可以通过放置新的和手动的析构函数调用(可怜的人)对a和的生命周期进行细粒度的控制。pending_fifostd::optional

这是一个例子:

#include <iostream>

struct A
{
    A() {std::cout << "A()\n";}
    ~A() {std::cout << "~A()\n";}
};

union B
{
    A a;
    B() {}
    ~B() {}
};

int main()
{
    B b;
}

在此,不B b;打印任何内容,因为a既不构造也不破坏。

如果BstructB()则将调用A(),然后~B()将调用~A(),您将无法避免这种情况。


23
@daoliker不一定是随机的,但您无法预测。与任何其他未初始化的变量相同。您不能假设它是随机的。所有你知道它可以保存用户的密码,您先前要求他们输入英寸
user253751

5
@daoliker:以前的评论太乐观了。随机字节的取值范围为0-255,但是如果您将未初始化的字节读入,则int可能会得到0xCCCCCCCC。读取未初始化的数据是未定义的行为,并且可能发生的情况是编译器只是放弃了该尝试。这不仅仅是理论。Debian犯了这个确切的错误,它破坏了他们的OpenSSL实现。他们有一些实际的随机字节,添加了一个未初始化的变量,编译器说“结果是不确定的,所以它很可能为零”。零显然不再是随机的了。
MSalters

1
@MSalters:您有此要求的消息来源吗?因为我发现这并不是发生的事情:不是将其删除的编译器,而是开发人员。老实说,如果任何编译器编写者做出如此难以置信的错误决定,我都会感到惊讶。(见stackoverflow.com/questions/45395435/...
杰克Aidley

5
@JackAidley:哪个确切的说法?您确实有很好的联系,似乎我把故事倒了。OpenSSL弄错了逻辑,并使用未初始化的变量,从而使编译器可以合法地承担任何结果。Debian正确地发现了这一点,但解决了问题。至于“编译器做出这样的错误决定”;他们没有做出这个决定。未定义行为是错误的决定。优化器旨在在正确的代码上运行。例如,GCC主动假定没有签名的溢出。假设“没有未初始化的数据”同样合理;它可以用来消除不可能的代码路径。
MSalters

1
@JackAidley我遇到了类似于@MSalters在我自己的代码中提到的问题;我错误地认为未初始化的变量将为空,并且在后续!= 0比较结果为true 时感到困惑。从那以后,我添加了编译器标志,将未初始化的变量视为错误,以确保不会再次陷入该陷阱。
汤姆·林特

0

简而言之,除非显式分配/初始化一个值,否则单个成员联合不会初始化分配的内存。此功能可以std:: optional在c ++ 17中实现。


2
那是一个误导性的答案。仅具有一个成员的联合将具有与该成员相同的大小。在初始化成员之前,不会初始化该内存。
基里尔·德米特连科
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.