-1

I'm trying to destroy an instantiation of a class using a destroyer. I also want to keep track of the numbers of class instances I created.


using namespace std;

class Asteroid
{
private:
    double posx,posy;
    static int i;

public:
    Asteroid(double x,double y)
    {
        posx=x;
        posy=y;
        i++;
        cout <<"Number of asteroids : "<<i<<endl;
    }
    ~Asteroid()
    {
        i--;
        cout <<"Number of asteroids : "<<i<<endl;

    }
    int pos()
    {

        cout <<"X : "<<this->posx<<" Y : "<<this->posy<<endl;

    }
} ;

int Asteroid::i=0;

int main()
{
Asteroid a(1,2);
a.pos();
a.~Asteroid();
a.pos();

    return 0;
}

Output:
Number of asteroids : 1
X : 1 Y : 2
Number of asteroids : 0
X : 1 Y : 2
Number of asteroids : -1

Desired output:
Number of asteroids : 1
X : 1 Y : 2
Number of asteroids : 0
X : 1 Y : 2 <-- I want this to be deleted from memory
Number of asteroids : -1 <-- 0 instead of a negative value

Rosalyo
  • 35
  • 4
  • 1
    `a.pos();` is Undefined Behaviour as the destructor of `a` has been explicitly called on the previous line. – Richard Critten Nov 13 '21 at 21:57
  • 1
    The `a` object will be destroyed at the end of `main`. Don’t **ever** call a destructor explicitly. (there is one situation where it’s okay, but you won’t encounter that for quite a long time, if at all) – Pete Becker Nov 13 '21 at 21:58
  • 1
    I think even without the call to `.pos`, since the destructor is not trivial this is undefined (double destruct). – kabanus Nov 13 '21 at 21:58
  • You also forgot to implement a copy constructor. Hillarity will ensue in the event any of these objects get copied, for any reason. – Sam Varshavchik Nov 13 '21 at 21:58
  • `int pos()` returns _what int, exactly_? Are you [compiling with warnings enabled](https://godbolt.org/z/76evb8czh)? – Drew Dormann Nov 13 '21 at 22:23
  • Why are you explicitly destroying an object that will go away anyway when it goes out of scope? – Paul Sanders Nov 13 '21 at 23:16

1 Answers1

0

In general, calling a destructor explicitly quickly leads to undefined behavior, in your example this is a bit more obvious - calling .pos on a destructed object. Even without that, only simple destructors (empty ones) can be called multiple times, and your destructor will be called again at the lifetime end of the object (end of main in your example, leading to negative asteroids.).

If this is an XY question, and what you want is to keep a game board/state of asteroid locations and number, then you can have one class manage that, with no memory shenanigans. For a fixed grid of placements (i.e, pixelated) an array is enough to hold the locations of all objects, with an additional integer to count them.

Without going in to the complexities needed to properly keeping object counter up keep (not hard, but tedious - you forgot a copy constructor and assignment just at a glance, though maybe it's better to delete those in your example) if you really want to have something that manages memory in this fine-grained level, usually because you have some really real-time machine that needs to be super-performant in space and time (maybe a spaceship controller), then you have placement new which allows you to pre-allocate memory where you will construct objects. You can then construct and re-construct on said memory, and you would have to call the destructor yourself for each object such constructed, finally releasing the buffer at the end. I can't say I've ever seen someone use it though. One place it is used in "every day life" is the Vector template library for example, as Paul mentions in the comment.

kabanus
  • 22,925
  • 6
  • 32
  • 68