Dino Dino - 1 year ago 44
C++ Question

Object not deleted before new is assigned

I'm kind of confused, because I was sure this should work different. Take a look at this code example:

#include <iostream>
#include <string>

using namespace std;

class base
virtual ~base() = default;

class derived : public base
int a = 0;
int *b = nullptr;
std::string lol;

derived(std::string s) : b(new int(6)), lol{s} { cout << "ctor " << lol << endl; }
derived(derived const& d) : lol{d.lol + " copy"} {cout << "copy " << lol << endl; }

virtual ~derived() { cout << "dtor " << lol << endl; delete b; }

virtual void superFunction() { cout << "OMG " << lol << endl; }

int main()
derived a("a");
derived b("b");
a = b;

And the program output with all optimizations off is:

ctor a
ctor b
dtor b
dtor b

I was sure that in this case compiler should generate code that deletes object
and uses copy constructor to create new object. Instead it uses
that it implicitly declares.

Can someone explain why? Or point me to C++ standard.


Answer Source

When you write a = b;, compiler calls assignment operator, which will be automatically generated if not present in the code and not marked as deleted. Copy constructor is used only if you try to initialize a new object from another object like this:

derived a("a");
derived b = a;

Also, your code crashes before main returns as it tries to delete b, which points to the same memory from a and from b after a = b; default-assignment.

If you want to delete a with derived destructor after a = b; execution, all you need is copy-and-swap idiom. Here you may find a great answer on how to do that in legacy and modern C++. Proper implementation of rule-of-four from that answer will perfectly fit the DRY principle and help you to avoid memory issues. Note the fabulous trick with passing parameter to operator= by value, which makes compiler select the appropriate constructor (copy or move) and allows you to write only four methods instead of all five of them.