Question

I've used boost::variant for some time and now I'm trying to figure out how it internally works. I wrote a simple test and I can't understand the results. Here it is (simplified)

struct my_type
{
    my_type(){ cout << (size_t)this << " construction"; }
    ~my_type(){ cout << (size_t)this << " destruction"; }
};

int main()
{
    variant<int, my_type> x;
    x = my_type();
}

The output of such program is

140736940365327 construction  <-- A
140736940365236 destruction  <-- ?
140736940365327 destruction  <-- A
140736940365332 destruction  <-- ?

Why the hell the destructor is not called as many times as the constructor ? As destructors are called over the heap, I'm aware that this may not segfault, but it seems to me that this behaviour is dangerous. Am I missing something ? Is this related to the "backup" mechanism of boost::variant ?

Was it helpful?

Solution

You have only define a default constructor, but of course a constructor can be called with various parameters too. Since you do not explicitly define a copy constructor, (a constructor that takes a const my_type&), the compiler implicitly generates one for you. If you add your own copy constructor, you should see that it is used to construct the other two mysterious objects:

struct my_type
{
  my_type(){ cout << (size_t)this << " construction"; }
  my_type(const my_type&){ cout << (size_t)this << " copy construction"; }
  ~my_type(){ cout << (size_t)this << " destruction"; }
};

In fact, if you're using a C++11 compiler, an implicitly generated move constructor will be responsible for some of the new objects. If you provide a copy constructor as above, then the implicit move constructor is not generated any more and so they all show up as copy constructions. However, if you provide a move constructor too, you will find it being called:

struct my_type
{
  my_type(){ cout << (size_t)this << " construction"; }
  my_type(const my_type&){ cout << (size_t)this << " copy construction"; }
  my_type(my_type&&){ cout << (size_t)this << " move construction"; }
  ~my_type(){ cout << (size_t)this << " destruction"; }
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top