A union
будет достаточно большим, чтобы вместить самую большую переменную, объявленную в union
, чтобы можно было сохранить там объект любого из типов переменных, объявленных в union
.
Однакото, что хранится в union
, не отслеживается.Любой объект, хранящийся в union
, должен быть явно уничтожен как часть уничтожения объекта, содержащего union
, точно так же, как любой объект, хранящийся в union
, должен быть явно создан как часть конструирования объекта, содержащего union
.
Программист должен иметь какой-то механизм для отслеживания того, что хранится в union
, и для правильной обработки любых действий по созданию и уничтожению.
Это исправленопрограммисту для правильного доступа к тому, что хранится в union
, зная, что хранится в union
, а затем используя соответствующий элемент union
для доступа к этому объекту.
Программа, демонстрирующая использованиеa union
Начиная с источника из других ответов, я расширил этот источник, чтобы продемонстрировать разницу между union
членом struct
и struct
членом struct
.
В приведенном ниже коде для конструкторов union
, содержащих класс u
, и для класса yes
, и для класса no
.Кроме того, у меня есть конструктор по умолчанию, конструктор копирования и оператор присваивания для класса u
.
В дополнение к двум указанным вами структурам yes
и no
я также предоставилтретий struct
, place
, который не используется в union
, а является просто другой переменной-членом.
Каждый из различных классов / структур имеет статический счетчик, который подсчитывается каждый раз, когдапостроено.
Я предоставил оператор присваивания для struct
из u
, чтобы правильно обработать присвоение.Оператор присваивания по умолчанию представлял собой побитовую копию, и я хотел сохранить уникальный идентификатор для каждого экземпляра для надлежащего документирования отслеживания строительства и разрушения.
union
против struct
и содержащий создание / разрушение объекта
Обратите внимание, что в выводе, сгенерированном этой программой, когда создается class
, содержащий union
, структура place
не создается, однако ни одна из union
членов построено.И когда class
, содержащий union
, разрушается, структура place
разрушается, однако ни один из union
членов не разрушается.
Вы также можете увидеть в выводе, где создаются временные переменные, используется, а затем разрушен.Однако обратите внимание, что когда временное значение назначается в union
, деструктор никогда не вызывается.
Таким образом, в программе есть такая простая область действия с парой операторов.
{
std::cout << "scope in" << std::endl;
std::cout << " create uu from n" << std::endl;
u uu(n);
std::cout << " assign y to uu" << std::endl;
uu = y;
std::cout << " assign n to uu" << std::endl;
uu = n;
std::cout << "scope out" << std::endl;
}
И раздел вывода, который я аннотировал несколькими примечаниями, соответствующими этому разделу источника:
scope in
create uu from n
no-cc : 0 -> 1 --- create a temporary struct no for the call to construct
no-cc : 1 -> 2 --- assignment of temporary to union through copy construction
place-c : 1 --- construct non-union struct member
u-c - no: 1 place 1 tu: 2 tu_no: 2
no-d : 1 --- destruct the temporary passed to the constructor
assign y to uu
yes-cc : 0 -> 1 --- create a temporary struct yes for the assignment
yes-cc : 1 -> 2 --- assignment of temporary to union through copy construction
place-c : 2 --- construct non-union struct member
u-c - yes: 2 place 2 tu: 1 tu_yes: 2 --- construct temporary union member using yes version of the constructors
yes-d: 1 --- destruct the temporary used in assignment
u-= : 2 into 1 o.place 2 tu: 1 tu_yes: 2
u-d : 2 tu: 1 tu_yes: 2 --- destruct temporary union struct
place-d : 2 --- destruct non-union struct member
assign n to uu
no-cc : 0 -> 3 --- create a temporary struct no for the assignment
no-cc : 3 -> 4 --- assignment of temporary to union through copy construction
place-c : 3
u-c - no: 3 place 3 tu: 2 tu_no: 4 --- construct temporary union using no version of constructors
no-d : 3 --- destruct the struct no temporary
u-= : 3 into 1 o.place 3 tu: 2 tu_no: 4
u-d : 3 tu: 2 tu_no: 4 --- destruct the struct union temporary
place-d : 3
scope out
с последующим уничтожением экземпляра u
, созданного в области видимости при выходе переменнойобласти действия с:
u-d : 1 tu: 2 tu_no: 2
place-d : 1
Обратите внимание, что у нас есть экземпляр no
, идентификатор экземпляра 2 и экземпляр yes
, идентификатор экземпляра 2, что мы никогда не видим сообщение деструктора.Это временные файлы, которые на самом деле хранятся в union
.Обратите внимание, что каждый экземпляр члена place
разрушается, так как разрушается его контейнер u
.
Исходный код и выходные данные для union
пример
Исходный код этой демонстрационной программы:
// union_test.cpp : This file contains the 'main' function. Program execution begins and ends there.
// /12049433/otkuda-c-union-uznaet-tip-hranimogo-v-nem-i-kakoi-destruktor-vyzyvat
#include "pch.h"
#include <iostream>
struct yes {
yes() : n(nc++) { std::cout << " yes-c: " << n << std::endl; }
yes(yes const& o) : n(nc++)
{
std::cout << " yes-cc : " << o.n << " -> " << n << '\n';
}
~yes() { std::cout << " yes-d: " << n << std::endl; }
int n = 0; // identifier number for specific instance
static int nc; // count of number of instances of this class created, instance identifier
};
struct no {
no() : n(nc++) { std::cout << " no-c : " << n << std::endl; }
no(no const& o) : n(nc++)
{
std::cout << " no-cc : " << o.n << " -> " << n << '\n';
}
~no() { std::cout << " no-d : " << n << std::endl; }
int n = 0; // identifier number for specific instance
static int nc; // count of number of instances of this class created, instance identifier
};
struct place {
place() : n(nc++) { std::cout << " place-c : " << n << std::endl; }
place(no const& o) : n(nc++)
{
std::cout << " place-cc : " << o.n << " -> " << n << '\n';
}
~place() { std::cout << " place-d : " << n << std::endl; }
int n = 0; // identifier number for specific instance
static int nc; // count of number of instances of this class created, instance identifier
};
struct u {
union {
yes y;
no n;
};
place p; // non-union to see construction/destruction of non-union.
int nu = 0; // identifier number for specific instance
int tu = 0; // indicator as to type currently in the union
static int nc; // count of number of instances of this class created, instance identifier
u() : nu(nc++) { std::cout << " u-c : " << nu << " place " << p.n << " tu: " << tu << std::endl; }
u(yes _y) :y(_y), nu(nc++), tu(1) {
std::cout << " u-c - yes: " << nu << " place " << p.n << " tu: " << tu;
switch (tu) {
case 0:
std::cout << std::endl;
break;
case 1:
std::cout << " tu_yes: " << y.n << std::endl;
break;
case 2:
std::cout << " tu_no: " << y.n << std::endl;
break;
default:
std::cout << "Unknown tu: " << tu << std::endl;
break;
}
}
u(no _n) :n(_n), nu(nc++), tu(2) {
std::cout << " u-c - no: " << nu << " place " << p.n << " tu: " << tu;
switch (tu) {
case 0:
std::cout << std::endl;
break;
case 1:
std::cout << " tu_yes: " << y.n << std::endl;
break;
case 2:
std::cout << " tu_no: " << y.n << std::endl;
break;
default:
std::cout << "Unknown tu: " << tu << std::endl;
break;
}
}
u(u const& o) : nu(nc++), tu(o.tu)
{
std::cout << "u-cc : " << o.nu << " -> " << nu << " tu: " << tu << " o.place " << o.p.n;
switch (tu) {
case 0:
std::cout << std::endl;
break;
case 1:
std::cout << " tu_yes: " << o.y.n << std::endl;
break;
case 2:
std::cout << " tu_no: " << o.n.n << std::endl;
break;
default:
std::cout << "Unknown tu: " << tu << std::endl;
break;
}
}
u & operator = (const u & o)
{
std::cout << "u-= : " << o.nu << " into " << nu << " o.place " << o.p.n << " tu: " << o.tu;
tu = o.tu;
switch (o.tu) {
case 0:
std::cout << std::endl;
break;
case 1:
std::cout << " tu_yes: " << o.y.n << std::endl;
break;
case 2:
std::cout << " tu_no: " << o.n.n << std::endl;
break;
default:
std::cout << "Unknown tu: " << tu << std::endl;
break;
}
return *this;
}
~u() {
std::cout << " u-d : " << nu << " tu: " << tu;
switch (tu) {
case 0:
std::cout << std::endl;
break;
case 1:
std::cout << " tu_yes: " << y.n << std::endl;
break;
case 2:
std::cout << " tu_no: " << n.n << std::endl;
break;
default:
std::cout << "Unknown" << std::endl;
break;
}
}
};
int yes::nc = 0;
int no::nc = 0;
int place::nc = 0;
int u::nc = 0;
int main()
{
std::cout << "create uu" << std::endl;
u xx;
std::cout << "create y" << std::endl;
yes y;
std::cout << "create n" << std::endl;
no n;
{
std::cout << "scope in" << std::endl;
std::cout << " create uu from n" << std::endl;
u uu(n);
std::cout << " assign y to uu" << std::endl;
uu = y;
std::cout << " assign n to uu" << std::endl;
uu = n;
std::cout << "scope out" << std::endl;
}
xx = y;
return 0;
}
И вывод, сгенерированный этой программой.
create uu
place-c : 0
u-c : 0 place 0 tu: 0
create y
yes-c: 0
create n
no-c : 0
scope in
create uu from n
no-cc : 0 -> 1
no-cc : 1 -> 2
place-c : 1
u-c - no: 1 place 1 tu: 2 tu_no: 2
no-d : 1
assign y to uu
yes-cc : 0 -> 1
yes-cc : 1 -> 2
place-c : 2
u-c - yes: 2 place 2 tu: 1 tu_yes: 2
yes-d: 1
u-= : 2 into 1 o.place 2 tu: 1 tu_yes: 2
u-d : 2 tu: 1 tu_yes: 2
place-d : 2
assign n to uu
no-cc : 0 -> 3
no-cc : 3 -> 4
place-c : 3
u-c - no: 3 place 3 tu: 2 tu_no: 4
no-d : 3
u-= : 3 into 1 o.place 3 tu: 2 tu_no: 4
u-d : 3 tu: 2 tu_no: 4
place-d : 3
scope out
u-d : 1 tu: 2 tu_no: 2
place-d : 1
yes-cc : 0 -> 3
yes-cc : 3 -> 4
place-c : 4
u-c - yes: 4 place 4 tu: 1 tu_yes: 4
yes-d: 3
u-= : 4 into 0 o.place 4 tu: 1 tu_yes: 4
u-d : 4 tu: 1 tu_yes: 4
place-d : 4
no-d : 0
yes-d: 0
u-d : 0 tu: 1 tu_yes: -858993460
place-d : 0