If you have the address of a data member of some class, is there a generic way to retrieve the unique object that has that address for this data member? Or do I have to write a function and search through all the objects of that class(including all the containers containing objects of that class) to find out which one it is? I suspect there must be a more generic and efficient way. Besides, the function I write would only work for that particular data member for that particular class--not cool at all.
Any way to do it would be arguably unsafe because there is no way to ensure that the object pointed to is actually owned by the class you think it is. (So yeah there are ways to do it.. but you shouldn't)
This raises a red flag in my brain that you're doing something you probably shouldn't be.
The obvious solution to me is.... if you need to access the owner of this member... keep a pointer to the owner instead of a pointer to its individual member.
And in fact... code outside of the class in question shouldn't even be aware of any of that class's members as it violates encapsulation.
Hmm... Well at first I was using pointers to the objects themselves, but I discovered painfully that their addresses got shifted during push_back and resize of the containers containing them, which caused a lot of bugs, so I'm instead using a pointer to a particular data member of the class where the address won't change spontaneously.
Well at first I was using pointers to the objects themselves, but I discovered painfully that their addresses got shifted during push_back and resize of the containers containing them
Perhaps you could use a container such as std::deque where that won't happen (as long as you are only adding to either of the ends ?)
Errr... you'll have the same problem with pointers to members. When the object is moved in memory... so are all its members.
If you want to prevent the object from moving in memory, one way to do it is to allocate the object dynamically and push a pointer into the vector rather than the actual object. Using a smart pointer means the object never needs to be cleaned up:
1 2 3 4 5 6 7
// Instead of this:
std::vector< Foo > v;
v.push_back( whatever );
// Do this:
std::vector< std::unique_ptr<Foo> > v;
v.emplace_back( new Foo(whatever) );
Then to get a pointer to an object:
1 2 3
// get a pointer to object at index [3]:
Foo* ptr = v[3].get();
The object will now never be moved in memory, even if you resize the vector... and your 'ptr' pointer will stay valid as long as the object has not been destructed (so as long as you do not remove it from the vector -- as it will be automatically destructed once it is removed)
Rats! Really??? I conducted a thorough test and I found no change in the address of data member "name" of class Person. This is a sample output from my tests. Here v is a vector containing objects of Person, and NameAdress() returns the address of the private data member name. I was convinced that it would not change despite all the changes of the object's addresses as the vector got constantly resized. Here v[3]'s address gets shifted 4 times as v got resized, but I found no change in the address of v[3].name.
A variable occupies a block of memory.
An object is a group of variables.
Therefore an object is a larger block of memory ... with smaller parts of that block being the space for each one of its individual members.
If you move the object... then you also move all the members... because that's what the object is.
It'd be like putting a bunch of toys (variables) in a box (object). When you move the box, all the toys move with it.
I don't know what NameAddress is doing, so I can't speak to the efficacy of your test.
The only way I can see that you are not experiencing this problem is:
1) NameAddress is giving you the wrong address and does not actually reflect the address of the variable
2) NameAddress is not returning a pointer to a member, but rather is returning a member that is a pointer.
I can elaborate further but I'd need to see NameAddress (as well as the definition of this 'name' variable)
Rats! Really??? I conducted a thorough test and I found no changed in the data member name of class Person.
Is the data member a pointer to dynamic memory? If it is, you're not actually storing a pointer to a data member in the other class. You're storing a copy of a pointer, and that is safe enough. The location of the dynamic memory won't change unless the containing class does something to affect it.
As I mentioned before, you might consider using a std::deque if you want a pointer to the containing object. Pointers to contained objects won't be invalidated with calls to push_back, push_front or resize.
As I mentioned before, you might consider using a std::deque if you want a pointer to the containing object. Pointers to contained objects won't be invalidated with calls to push_back, push_front or resize.
The only way I can see that you are not experiencing this problem is:
1) NameAddress is giving you the wrong address and does not actually reflect the address of the variable
2) NameAddress is not returning a pointer to a member, but rather is returning a member that is a pointer.
I can elaborate further but I'd need to see NameAddress (as well as the definition of this 'name' variable)
class Person {
private:
string *name;
int age, height, ....
After 10,000 iterations of the vector resizing of v, all the address changes of the Person object v[3] were:
0x34a8c
0x35ca4
0x37eec
0xa506b4
0xa59754
0xa6b55c
0xa8f674
0xb5068c
0xbe068c
0xd0068c
0xf3068c
0x138068c
v[3].NameAddress() stayed the same throughout at 0x34380.
I made name a pointer because in my program, people's names are constantly changing, which would corrupt "who knows whom" if I didn't make name a pointer, though I did try using the addresses the objects themselves first. But I do agree that your solution is best, using unique_ptr. But I don't have C++11, and really want to learn and use it now.
So now that you know what 'name' really is in Person, is it still unsafe to seek a generic method to retrieve the object Person with given data member address name? I've written a particular function to do that, which only works for my particular program, but a generic method that will work for any code would be a bad idea?
I made name a pointer because in my program, people's names are constantly changing, which would corrupt "who knows whom" if I didn't make name a pointer, though I did try using the addresses the objects themselves first.
Yeah... see that makes more sense. People know other people so it makes more sense for them to have a pointer to the person... not just the person's name.
But I don't have C++11, and really want to learn and use it now.
std::unique_ptr, std::shared_ptr, and std::weak_ptr are super amazing. If there's one thing from C++11 to get ASAP it's them.
If your compiler does not support C++11 and you aren't willing to upgrade... you can always install the 'boost' library. It has implementations of the above mentioned classes and AFAIK the interface is 100% identical to C++11's version.
EDIT: On a completely unrelated and funny side note... When I saw this:
people's names are constantly changing
My brain got confused for a second because I saw the 'const' but then the rest of the sentence went on to have the exact opposite meaning.
I think he's right. The test that I conducted, I changed the container from vector to deque. Absolutely no change to the address of the object as the deque got resized 1,000,000 times!