Is there any way to destory objects in if scope

closed account (DEhqDjzh)
I am creating a game and i have to destroy player when it collides with an enemy. But the player is a stack object. So must i create a player in heap in order to destroy it (with delete)?
e.g:
1
2
3
4
5
6
7
8
 
if(collide_with_Ground)
{
 // destroy the player

}

 
Normally you should avoid new and delete in modern C++

One way to do it is to give the player functions like bool alive() and void die()
In this case you don't need to create it on the heap.

Another option would be to use a smart_ptr and call release on it.
Yeah, you can directly invoke the object's destructor. Of course, you shouldn't do that for a number of compelling reasons.

This is almost certainly an XY Problem. Please carefully read
http://xyproblem.info/
And then report back.
1
2
3
4
Player player(some_initialization);

if (some_condition)
    player = Player(); //default constructor gives a "null" object 

Conceptually, destructing the Player and nothing else is strange. Normally the Player should have the same lifetime as the Game. If there's no player, why is the game running?
closed account (E0p9LyTq)
If there's no player, why is the game running?

Demo mode. AKA as Attraction Mode.

Showing a subset of game action to make people want to shove coins in the slot.

Arcade games use it.
In that case it's not like there's no player, in the sense of faction. There's a player character that's being controlled by the computer. IMO that should be modelled as a Player where the input is coming from someplace other than the human.
yeah I agree with other say, just make a flag in the player class stating if the player is dead or alive and then check if the player is dead or alive
.. ?
any stl container can destroy an object, though vectors are a bit clunky about it. Put all players in a list or something and kill them as needed?

you can also bracket it for destruction if for some unconvincing reason it needs to be on the stack:

{
player x;
while (x.isalive())
{
stuffs;
}
} //goodbye x, it exists no more.


whether this makes any sense at all in your program or not is another story. Careful use of threading inside its lifespan brackets could make this design work, but its not terribly good code or a great approach. The only time I have ever done this was to rid myself of some very large intermediate objects that were hogging memory, though we do it all the time in for loops for the loop variable and small things like that (rarely objects).

Which means this should have been obvious as well:

for(object x ; !x.collide();)
{
stuffs.
} //x goes away here too.

Keep in mind that I don't judge too much. This is a case of just because you can do something does not make it good code. Its hard to make this clean, because you probably don't want you main thread stuck in a loop dealing with this, and a big loop around everything is also yucky, so the applications of this are reduced greatly by what you can sensibly put inside one pair of {} and still have a good program.
Last edited on
I think the point is that OP's code is not structured like that.
1
2
3
4
5
6
7
8
9
10
Player player;
while (true){
    something_happens(player, other_stuff);
    if (some_condition())
        kill(player);
}

void kill(Player &player){
    //???
}
OP wants the Player to be destructed or to change to an invalid state without the object going out of scope.
If constructs like if( this_player.is_alive() ) { /* then do something with this_player */ }
would be scattered throughout the code,
a stylised way of making the code look much neater is by using zombie objects (aka null objects).
https://sourcemaking.com/design_patterns/null_object

For instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <string>
#include <new>

struct player
{
    explicit player( std::string name = {} ) : name( std::move(name) ) {}
    virtual ~player() = default ;
    // TO DO: rest of rule of five defaults

    virtual void play() { std::cout << name << " plays\n" ; }

    std::string name ;
    // ...
};

struct zombie : player
{
    using player::player ;
    // note: there are no additional member variables

    virtual void play() override { /* do nothing */ }
};

player& kill( player& p )
{
    static_assert( sizeof(zombie) == sizeof(player) ) ;

    std::cout << "kill " << p.name << '\n' ;
    p.~player() ;
    return * new ( std::addressof(p) ) zombie ;
}

int main()
{
    player team[] { player{"Muslera"}, player{"Caceres"}, player{"Godin"},
                    player{"Bentancur"}, player{"Suarez"}, player{"Cavani"} } ;

   for( player& p : team ) p.play() ;

   std::cout << '\n' ;
   for( int i : { 0, 2, 3 } ) kill( team[i] ) ;
   std::cout << '\n' ;

   for( player& p : team ) p.play() ;
}

http://coliru.stacked-crooked.com/a/f0730da6bc07fbeb
Topic archived. No new replies allowed.