Reputation: 500
I'm a beginner programmer, and I was wondering...
I need a unique ID for my object in a game
so I thought I define a global class that holds the global id, and when I call the constructor of an object it will be incremented, while calling the destructor of that object it decrements it.
Is it true that for every constructor call there will be a corresponding destructor?
class id_holder{
private:
int id_count;
public:
id_holder() {id_count = 0 ; std::cout<< "unique_id: I'm constructed"<<std::endl;}
~id_holder(){std::cout<<"unique_id: I'm destructed"<<std::endl;}
void increment_id(){id_count ++;};
void decrement_id(){id_count --;};
int get_id() {return id_count;};
};
class BaseObject {
protected:
void increment_id();
void decrement_id();
public:
virtual ~BaseObject(){decrement_id();}
BaseObject();
BaseObject(V2 pos, ObjectType idobj, double s, Color col);
};
BaseObject::BaseObject(){
//stuff
increment_id();
unique_id = bObj_id_counter.get_id();
}
BaseObject::BaseObject(V2 pos, ObjectType idobj, double s, Color col){
//stuff
increment_id();
unique_id = bObj_id_counter.get_id();
}
void BaseObject::increment_id(){
bObj_id_counter.increment_id();
}
void BaseObject::decrement_id(){
bObj_id_counter.decrement_id();
}
side question... is it possible to compare the memory adresses (this should be a unique id enough) of the objects instead of using an id_holder?
Upvotes: 2
Views: 228
Reputation: 21900
Is it true that for every constructor call there will be a corresponding destructor?
Yes, unless you allocate objects using operator new and don't destroy them, or, that your application ends abnormally.
Your solution should work well, unless you use it concurrently. You should provide exclusive access to that global object if you do so, though i don't think this is the case.
is it possible to compare the memory adresses (this should be a unique id enough) of the objects instead of using an id_holder
You could do it, every object will have a unique memory address. It's a kind of dirty solution, depending on what is your objective.
Upvotes: 4
Reputation: 19032
This is typically called "reference counting" and it has a wide range of uses. Yes it is possible to do, but yours won't quite work correctly just yet.
id
held statically, and then use the curiously recurring template pattern to ensure that this id
is global only for specific types. Then each type gets a copy of the global id
during construction.increment_id()
and decrement_id()
are called by the id_holder
class, there is no reason to call them again in your BaseObject
constructor/destructor.This is a relatively elegant solution that allows for you to do things like constant-time lookups for an item given its ID. For example:
template <class T>
class counter
{
static size_t global_id_;
size_t id_;
public:
counter() : id_(global_id_++) {}
counter(const counter&) : id_(global_id++) {}
~counter() {}
counter& operator=(const counter&)
{
// left as an exercise for the reader
// as what to do in this case is highly
// dependent upon the application
}
};
class counted_object : public counter<counted_object>
{
// stuff
};
Now you could hold a lookup table of counted_objects
stored in a vector for very quick lookups:
std::vector<counted_object*> lookup;
counted_object* o416 = lookup[416];
Upvotes: 1
Reputation: 3669
Yes, it is, and yes you can compare the addresses. Only problem is if you have memory leaks and the objects don't get deleted.
Every object has a unique address. Even if you create an empty class or struct, it's size will not be zero(by language design). Be careful when passing the this
reference from a constructor when working with multiple threads, as your object might not be fully constructed.
EDIT: You can use this to your advantage to discover memory leaks. Assuming you delete every object you have created by the time the program exits (like a clean-up method), just see if you have any objects left.
EDIT2: Here's a very good article on object counting in C++
Upvotes: 0
Reputation: 7631
Yes, there will be a destructor for every class and the compiler will give you a default if you don't provide one. Look at C++ default destructor
Upvotes: 0
Reputation: 2628
No, that is not necessarily true. In every well behaved program there is a destructor call for every constructor call. But if, for example, objects constructed with new
aren't delete
d, there will be no destructor call.
Also, in your example you didn't implement a copy constructor which means, that you might account for more destructor calls than constructor calls.
Further, you didn't implement an assignment operator, either. If the default one is used, the object being assigned to will have the same unique_id
as the one being assigned from. (Assuming, unique_id
is a memeber of BaseObject
which you didn't declare in your code snippet.) So that would make your unique_id
quite "un-unique". ;-)
Upvotes: 3