user2655800
user2655800

Reputation: 161

C++ destructor called twice with stack allocated compound objects

I have a compound class (instance containing other instance, nor pointer, nor reference). When the container instance is destroyed, destructor of contained instance is called (I am ok with that, it's logic). But the issue is that if the contained instance is stack allocated destructor is called once again when reaching out of scope.

Is that a coding error or a compiler issue?

What is the cleanest way of fixing it?

Here is my sample:

#include <iostream>

using std::cout;
using std::endl;

class A {
public:
  int i;
  A(int i_) : i(i_) {
    cout << "A(): " << i << endl;
  }
  ~A() {
    cout << "~A(): " << i << endl;
  }
};

class B {
public:
  A a;
  int b;
  B(const A& a_) : a(a_) {
    cout << "B(): " << a.i << endl;
  }
  ~B() {
    cout << "~B(): " << a.i << endl;
  }
};

int main(void) {
  for(int c = 0; c < 3; ++c) {
    A a(c+1);
    B b(a);
    cout << b.a.i << endl;
  }
  return 0;
}

Output is:

A(): 1
B(): 1
1
~B(): 1
~A(): 1
~A(): 1
A(): 2
B(): 2
2
~B(): 2
~A(): 2
~A(): 2
A(): 3
B(): 3
3
~B(): 3
~A(): 3
~A(): 3

Compiler is gcc 7.3.0

Upvotes: 1

Views: 159

Answers (1)

hlt
hlt

Reputation: 6317

The destructor is only called once per object. What you don't see in your output is that when you construct b, you create a copy of a using the copy constructor (which in your case is compiler-generated). That doesn't produce any output, but of course the destructor of the copy is also called.

If we add output to the copy constructor, we can see what actually happens:

A(const A& a_) : i(a_.i) {
  cout << "A(const A&): " << i << endl;
}

The output shows that each A is copied once, leading to the "duplicated" (not really) destructor calls (live demo). If you want to avoid copying the object, look into C++11's std::move, which is explained in depth elsewhere on this site.

Upvotes: 4

Related Questions