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

 

Union declaration - cppreference.com

A union is a special class type that can hold only one of its non-static data members at a time. The class specifier for a union declaration is similar to class or struct declaration: union attr class-head-name { member-specification } attr - (since C++11)

en.cppreference.com

 

728x90

+ Recent posts