Question

In my program, I have objects (of the same class) that must all have a unique identifier. For simplicity and performance, I chose to use the address of the object as identifier. And to keep the types simple, I use (void*) as a type for this identifier. In the end I have code like this:

class MyClass {
public:
  typedef void* identity_t;
  identity_t id() const { return (void*)this; }
}

This seems to be working fine, but gcc gives me a strict-aliasing warning. I understand the code would be bad if the id was used for data transfer. Luckily it is not, but the question remains: will aliasing optimisations have an impact on the code produced? And how to avoid the warning?

Note: I am reluctant to use (char*) as this would imply the user can use the data for copy, which it can not!

Was it helpful?

Solution

You are violating logical constness returning the object as mutable in a const method.
As Neil points out, no cast is needed.

class MyClass {
public:
  typedef const void* identity_t;
  identity_t id() const { return this; }
};

OTHER TIPS

You could try using the type uintptr_t instead of void*. uintptr_t is a integer type that is defined as being big enough to hold any pointer value. And since it's not actually a pointer, the compiler won't flag any aliasing problems.

class MyClass {
public:
    typedef uintptr_t identity_t;
    identity_t id() const { return (identity_t)this; }
}

Try using

return static_cast<void*>(this);

This should be perfectly safe, any pointer should be able to be cast to void * without risk of loss.

I originally suggested dynamic_cast(this);, but after reading up a bit I think it adds no advantage, and since it's RTTI-only it's not a good solution in general.

By the way, I would make the returned value const, since the identity of an object cannot change.

I can't see any aliasing issues. However, you are casting away constness (since the id function is const), which the compiler might be unhappy about. Perhaps it'd be better to use const void* as your ID type.

Alternatively, cast the address to an integer type such as size_t. Then it is no longer a pointer, and aliasing becomes a non-issue.

Why not using type MyClass *?

Or type intptr_t?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top