Quando eu estava lendo o código-fonte seastar , notei que havia uma estrutura de união chamada tx_side
que tinha apenas um membro. Isso é algum truque para lidar com um determinado problema?
Para sua informação, colo a tx_side
estrutura abaixo:
union tx_side {
tx_side() {}
~tx_side() {}
void init() { new (&a) aa; }
struct aa {
std::deque<work_item*> pending_fifo;
} a;
} _tx;
union
vez destruct
é uma ou mais das diferenças entre os dois. É uma técnica bastante obscura, portanto, a menos que o autor original desse código apareça, não tenho certeza de que alguém possa lhe dar uma resposta autorizada sobre qual problema eles esperam resolver com isso (se houver).Respostas:
Porque
tx_side
é uma união,tx_side()
não inicializa / constrói automaticamentea
e~tx_side()
não a destrói automaticamente. Isso permite um controle refinado sobre a vida útila
epending_fifo
, por meio de chamadas de destruidoras novas e manuais (um homem pobrestd::optional
).Aqui está um exemplo:
Aqui,
B b;
imprime nada, porquea
não é construído nem destruído.Se
B
fosse umstruct
,B()
ligariaA()
e~B()
ligaria~A()
, e você não seria capaz de impedir isso.fonte
int
poderá obter0xCCCCCCCC
. Ler dados não inicializados é Comportamento indefinido, e o que pode acontecer é que o compilador simplesmente descarta a tentativa. Isto não é apenas teoria. O Debian cometeu esse erro exato e interrompeu a implementação do OpenSSL. Eles tinham alguns bytes aleatórios reais, adicionaram uma variável não inicializada e o compilador disse "bem, o resultado é indefinido, portanto pode ser zero". Zero obviamente não é mais aleatório.!= 0
comparação subsequente foi verdadeira. Desde então, adicionei sinalizadores de compilador para tratar variáveis não inicializadas como erros para garantir que não cairei nessa armadilha novamente.Em palavras simples, a menos que seja atribuído / inicializado explicitamente um valor, a união de membro único não inicializa a memória alocada. Essa funcionalidade pode ser alcançada
std:: optional
no c ++ 17.fonte