I got a class that when instantiated needs to obtain a few unique ids to work. Initially I thought using an static function that assigns and increments. I don't need them to be consecutive, only unique.
class A {
int id_1;
int id_2;
int id_3;
public:
static int last_id=0;
static int get_id(){ return A::last_id++; }
...
A(){ id_1 = A::get_id(); id_2 = A::get_id(); id_3 = A::get_id(); }
};
Now, I' thinking in going multithreading. I think the static function will be a bottleneck, since I'm constructing a few hundred thousand instances of these objects at the start. I don't destroy any instance until the end of the program, so after initialization they are fixed. Anyway they are not computed at compile time because the quantity depends of command-line arguments.
An alternative I was thinking of was using memory addresses, they are unique in a single computer at least.
Something like:
class A {
int* id_1;
int* id_2;
int* id_3;
public:
static int last_id=0;
static int get_id(){ return A::last_id++; }
...
A(){ id_1 = new int(0); id_2 = new int(0); id_3 = new int(0); }
~A() { delete id_1; delete id_2; delete id_3(); }
};
Then I would read the identifiers as the address of the pointers.
Question: Does this make any sense to use pointers like this?
You're really not that far off with your original solution. Don't prematurely optimize! Incrementing an int
is very cheap! My only suggestion would be to use std::atomic<int>
instead of int
.
class A {
int id_1;
int id_2;
int id_3;
static int get_id() {
static std::atomic<int> next_id(1);
return ++next_id;
}
public:
A() :
id_1(get_id()),
id_2(get_id()),
id_3(get_id())
{ }
// deal with copying by disabling
A(const A&) = delete;
A& operator=(const A&) = delete;
// move is okay
A(A&&) noexcept = default;
A& operator=(A&&) noexcept = default;
};
Assuming you don't create more than 2^31/3
instances of A
, you don't have to worry about overflow.
I've used something like the following as a quick hack in C before - when I needed some unique values that were only unique over the lifetime of the process.
constants.h
extern const void * id_1;
extern const void * id_2;
constants.c
const void * id_1 = &id_1;
const void * id_2 = &id_2;
No worry about cleanup etc since they're extern'd globals.
In C++ for a class instance you could use the same idea, but localized to the instance:
class A {
void* id_1;
void* id_2;
void* id_3;
public:
A(){ id_1 = &id_1; id_2 = &id_2; id_3 = &id_3; }
};
Note that the ids will only be unique while the instance exists - but you've said that they're allocated only destroyed at application exit - so you should be OK.
Note: I do consider this a hack, and with C++11s std::atomic
the solution provided by Travis Glockel above is as simple and more robust. However without C++11 implementing atomic or adding an atomic library is messy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With