使用union两个类,在这个简单的示例中,它会union记住存储在其中的最后一个类,并为该对象调用正确的析构函数:
#include <iostream>
using std::cout;
using std::endl;
struct yes{
yes(){cout<<"yes-c"<<endl;}
~yes(){cout<<"yes-d"<<endl;}
};
struct no{
no(){cout<<"no-c"<<endl;}
~no(){cout<<"no-d"<<endl;}
};
struct u{
union{
yes y;
no n;
};
u(yes _y):y(_y){}
u(no _n):n(_n){}
~u(){}
};
int main() {
yes y;
no n;
{
u uu(n);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
yes-c
no-c
no-d
no-d
yes-d
Run Code Online (Sandbox Code Playgroud)
因此,uu将为~no()union 调用正确的析构函数,就像它在构造union时记录类型一样.这是如何运作的?
简短回答:事实并非如此.
如果你添加一个拷贝构造函数,no你会看到实际上有三个 no对象被创建,但只有两个被破坏.
首先,您创建对象n.然后,当您通过值将其传递给u构造函数时,它将被复制一次到_n参数中.也就是说_n然后对象被复制到该uu.n构件.
析构是构造函数中的_n参数,也是u函数中的n对象main.
这是您的程序稍加修改,以添加复制构造函数并跟踪no对象:
#include <iostream>
struct yes{
yes(){std::cout<<"yes-c"<<std::endl;}
~yes(){std::cout<<"yes-d"<<std::endl;}
};
struct no{
no(){std::cout<<"no-c : "<<n<<std::endl;}
no(no const& o)
: n(o.n + 1)
{
std::cout << "no-cc : " << o.n << " -> " << n << '\n';
}
~no(){std::cout<<"no-d : "<<n<<std::endl;}
int n = 0;
};
struct u{
union{
yes y;
no n;
};
u(yes _y):y(_y){}
u(no _n):n(_n){}
~u(){}
};
int main()
{
yes y;
no n;
{
u uu(n);
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有优化或copy-elision,这将创建输出
yes-c no-c : 0 no-cc : 0 -> 1 no-cc : 1 -> 2 no-d : 1 no-d : 0 yes-d
输出no-c : 0用于n在main函数中创建对象.
输出no-cc : 0 -> 1用于复制到u构造函数参数_n.
输出no-cc : 1 -> 2用于将参数复制_n到联合n对象中.
输出no-d : 1是对_n参数的破坏.
输出no-d : 0是函数中n对象的破坏main.