25

In a system where registered objects must have unique names, I want to use/include the object's this pointer in the name. I want the simplest way to create ??? where:

std::string name = ???(this);

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • convert it as an hex string representing the address ? – Felice Pollano Oct 21 '11 at 13:33
  • See the answer to this question: http://stackoverflow.com/questions/1255366/how-can-i-append-data-to-a-stdstring-in-hex-format – tenfour Oct 21 '11 at 13:34
  • 1
    sounds like a bad idea: you're tying object's identity with its memory location: what if you try to move it in a future version of your application? Your code will break in very unpleasant ways. – akappa Oct 21 '11 at 13:36
  • Agree, if what you want is to have unique name for each object, just assign a different string in constructor of your class. – Eric Z Oct 21 '11 at 13:38
  • What is the output you'd like to see? – John Dibling Oct 21 '11 at 13:42
  • 1
    If your application can have multiple instances, your method could fail because difference instances may have the same (virtual) address. – Eric Z Oct 21 '11 at 13:45
  • I agree with akappa. This sounds like a bad idea. – David Hammen Oct 21 '11 at 13:47
  • @EricZ, even simpler, simpler `delete` then `new` in one instance and you could get the same address. – edA-qa mort-ora-y Oct 21 '11 at 14:01
  • That's true. But for a delete-then-new object, its address is unlikely to be conflicted w/ the address of another existing object, which is what OP asks, right? – Eric Z Oct 21 '11 at 14:12
  • why WHY WHY - Why do you want to go down this daft route? – Ed Heal Oct 21 '11 at 14:13
  • If my application has multiple instances, they are separate and it doesn't matter if they're only unique within each instance... not like running under the JVM. – Mr. Boy Oct 24 '11 at 08:17
  • "just assign a different string in constructor of your class" - not sure how that helps really. Still have to get the strong from somewhere, and adding a new arg to every class seems a bit cumbersome... this is a simple scenario only where a 3rd-party library will throw if you try to register a non-unique name. So the name doesn't have to match the memory address, it's just a cheap trick because I know every instance of type T _currently_ in existence will have different addresses... I don't _use_ the address string otherwise, only internally. – Mr. Boy Oct 24 '11 at 08:19

6 Answers6

49

You could use string representation of the address:

#include <sstream> //for std::stringstream 
#include <string>  //for std::string

const void * address = static_cast<const void*>(this);
std::stringstream ss;
ss << address;  
std::string name = ss.str(); 
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 1
    I tested without the cast to void*, and it worked too. Is it necessary for some reasons ? – Willy Apr 07 '15 at 15:44
  • 7
    `ss << this` might invoke `operator<<` which accepts `T const * const` as argument, in which case you'll not get the address as string. Here is what I mean : http://coliru.stacked-crooked.com/a/cded799e93012de6 – Nawaz Apr 07 '15 at 16:10
  • A simpler one-liner that doesn't require a whole stringstream: `std::string address = std::to_string((unsigned long long)(void**)this);`, which also works if you need the address as an integer, not a string: `unsigned long long address = (unsigned long long)(void**)this;` – KulaGGin Apr 20 '23 at 16:31
10

You mean format the pointer itself as a string?

std::ostringstream address;
address << (void const *)this;
std:string name = address.str();

Or ... yes, all the other equivalent answers in the time it took me to type this!

Useless
  • 64,155
  • 6
  • 88
  • 132
4
#include <sstream>
#include <iostream>
struct T
{
    T()
    {
        std::ostringstream oss;
        oss << (void*)this;
        std::string s(oss.str());

        std::cout << s << std::endl;
    }
};

int main()
{
    T t;
} 
mloskot
  • 37,086
  • 11
  • 109
  • 136
2

You could use ostringstream the this pointer's address and put that ostringstream's value as string?

1

A simpler one-liner that doesn't require a whole stringstream:

std::string address = std::to_string((unsigned long long)(void**)this);

Also implied, works with pointers of any time, not just this. Also works if you just need it as an integer:

unsigned long long address = (unsigned long long)(void**)this;

You can replace unsigned long long with a type alias that is provided by the system. On Windows it's uintptr_t.

KulaGGin
  • 943
  • 2
  • 12
  • 27
0

In a system where registered objects must have unique names, I want to use/include the object's this pointer in the name.

An object's address is not necessarily unique. Example: You dynamically allocate such an object, use it for a while, delete it, and then allocate another such object. That newly allocated object might well have the same the object address as the previous.

There are far better ways to generate a unique name for something. A gensym counter, for example:

// Base class for objects with a unique, autogenerated name.
class Named {
public:
  Named() : unique_id(gensym()) {}
  Named(const std::string & prefix) : unique_id(gensym(prefix)) {}

  const std::string & get_unique_id () { return unique_id; }

private:
  static std::string gensym (const std::string & prefix = "gensym");
  const std::string unique_id;
};  

inline std::string Named::gensym (const std::string & prefix) {
  static std::map<std::string, int> counter_map;
  int & entry = counter_map[prefix];
  std::stringstream sstream;
  sstream << prefix << std::setfill('0') << std::setw(7) << ++entry;
  return sstream.str();
}   

// Derived classes can have their own prefix. For example,
class DerivedNamed : public Named {
public:
  DerivedNamed() : Named("Derived") {}
};  
David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • 4
    But once the first object is destroyed, it doesn't exist. So the address IS unique... if I destroy the first object, it is also unregistered from the data-structure requiring a name. – Mr. Boy Oct 24 '11 at 15:07