constructor/destructor 가 있는 class 들을 union 으로 사용할 일이 없어서 몰랐는데 member 간 전환할 때 명시적으로 destructor 와 placement new 를 호출해주자.
#include <iostream>
#include <string>
#include <vector>
union S
{
std::string str;
std::vector<int> vec;
~S() {} // needs to know which member is active, only possible in union-like class
}; // the whole union occupies max(sizeof(string), sizeof(vector<int>))
int main()
{
S s = {"Hello, world"};
// at this point, reading from s.vec is undefined behavior
std::cout << "s.str = " << s.str << '\n';
s.str.~basic_string();
new (&s.vec) std::vector<int>;
// now, s.vec is the active member of the union
s.vec.push_back(10);
std::cout << s.vec.size() << '\n';
s.vec.~vector();
}
위 예제를 보면 std::string, std::vector<int> 형식의 member 를 가진 union type S 가 있다. S.str 사용 후 vec member 를 사용하려고 할 때 destructor (~basic_string()) 와 placement new(new (&s.vec) std::vector<int>) 를 명시적으로 호출해주는 것을 볼 수 있다. 위와 같이 명시적으로 호출해주지 않으면 해당 객체의 virtual table 이 이상해져서 access violation exception 이 발생할 수 있다.
참고 : https://en.cppreference.com/w/cpp/language/union
728x90