Listing
Listing

Reputation: 1201

C++ self referencing class

I have to admit my C++ is a bit rusty. In a project I try to create a vector of classes and use them. There is a problem because I want to identify each entry of the vector with a unique pointer to it for fast access but it does not work. Here is a minimal example of my problem:

#include <iostream>
#include <vector>

class Foo{
public:
Foo() { ptr = this; }
~Foo() {}
Foo * ptr;
};

int main()
{
std::vector<Foo> vec;
for(unsigned int i = 0; i < 2; ++i)
  vec.push_back(Foo());
for(unsigned int i = 0; i < vec.size(); ++i)
 std::cout << "Object Self-Pointer: " << std::hex << reinterpret_cast<unsigned int>(vec[i].ptr) << std::endl; 
}

Actual output:

Object Self-Pointer: bfbebc18
Object Self-Pointer: bfbebc18

Intended output:

Object Self-Pointer: bfbebc18
Object Self-Pointer: bfbebc1c

(some pointers to the actual objects).

I hope you can help me with this issue, thank you in advance.

Upvotes: 2

Views: 11492

Answers (4)

JohnMcG
JohnMcG

Reputation: 8815

As others have mentioned, the problem is that push_back pushes a copy of the object onto the stack, which is created using the copy constructor, which does a memberwise copy of the member variable.

One way to address this would be to define a copy constructor to do what you want; e.g.:

Foo(const Foo& rhs) { ptr = this;}

Running with this, I got the output:

Object Self-Pointer: 4b0308
Object Self-Pointer: 4b030c

Upvotes: 1

akhisp
akhisp

Reputation: 675

std::vector stores copies of the object (it is a requirement that type of object is copy-constructable). In this case, Foo's copy-constructor is auto generated by the compiler.

So when you do push_back(Foo()), you're doing:

1) Create a Foo() object. Set ptr to bfbebc18
2) Copy it, and put it into vector<Foo>
3) Delete the original Foo from which it came
4) Create a new Foo() object. Set ptr to bfbebc18 (the same location is used because it's temporary)
5) Copy it and put it into vector<Foo>

Upvotes: 3

hmjd
hmjd

Reputation: 122001

When you call push_back(Foo()) an object is constructed and then vector will take a copy of that object. As Foo is using the default copy constructor it will store the this pointer of the temporary object created by Foo(). The address of the temporary object appears to be the same in both iterations of the loop.

Upvotes: 1

Asaf
Asaf

Reputation: 4407

When you do this:

vec.push_back(Foo());

A new temporary Foo object is created, but each time it is created in the same address (because it is created on stack and the stack pointer is the same). So the this pointer, and therefore the ptr member of each of these instances is the same.

When you add each instance to the vector, the default copy constructor is called, so the ptr member is copied, and therefore all instances in the vector have the same value.

Upvotes: 10

Related Questions