c++ vector push_back with pointers - c++

I'm trying to get my head around solving the following problem. I have the following function which accepts a const reference to an object. What I want to do, is give storage, a pointer to the object component is referencing. However, when I call storage.push_back() changes the object component is referencing (it's member data gets corrupted)
I'm just trying to store a pointer to the same object component is referencing, not alter the object at all.
void InputSystem::RegisterInputAcceptingEntity(const PlayerInputComponent &component) {
auto *cpy = &component;
std::vector<const PlayerInputComponent*> storage;
storage.push_back(cpy);
}
Why would the above code at all change the object component is referencing?
edit: Ok I edited the vector to contain constant pointers.
Here are some screenshots showing exactly what is happening. Here in the callee, if we inspect the argument that is going to be passed by reference, we can see the input_component member is not corrupted.
url to image: http://i.imgur.com/lKpRm.png
However, in the second image, just after stepping into the above said method:
url to image: http://i.imgur.com/x0Vdn.png
I've been under the impression that passing by const reference, there should be no way for the objects to differ inside/outside the function. I don't see why the object would be altered at all, if passed by const reference.

First, run your code through valgrind and see where the corruption is actually occurring. Pushing a pointer onto an array should not do anything to the data being pointed to.

Related

Array of pointers holds the same value for all elements

I'm currently deep-diving into the way pointers work.
Something for me unexplainable happened when executing the following lines of code:
std::vector<OptimizerPlanOperatorPtr> sources;
for (const auto &source : sourceOperators){
OptimizerPlanOperator planOperator = OptimizerPlanOperator(source);
sources.push_back(static_cast<std::shared_ptr<OptimizerPlanOperator>(&planOperator));
}
all sourceOperators differ, however when checking the elements of sources, they all point to the same OptimizerPlanOperator.
When I ran the debugger, I realized that in every loop step, all values of sources
change to the recent value.
My assumption is, that I poorly initialized the pointer here which somehow results in the value the pointer refers to being overridden.
Can somebody show a solution or explain, what I did wrong here?
You are storing the location of an object whose lifetime ends with the current iteration and handing ownership of it to a shared_ptr. Both are problems that lead to undefined behaviour.
Casting a pointer to std::shared_ptr does not automagically make the pointed-to object into a shared object and extend its lifetime, and it is equivalent to std::shared_ptr<OptimizerPlanOperator>(&planOperator).
The simplest solution is to not do this stepwise but all at once:
for (const auto &source : sourceOperators){
sources.push_back(std::make_shared<OptimizerPlanOperator>(source));
}
Your planOperator is a local variable on the stack, and when you are passing it to the cast static_cast<std::shared_ptr<OptimizerPlanOperator>(&planOperator), you are passing in the address of a local variable, so as soon as the iteration is over, that pointer &planOperator becomes garbage.

C++ Modifying object pointer points to but value is not preserved

The setup is I have an object and below that object is a secret pointer.
This pointer points to an object of the same class but a different object than the one above it.
I have a function that takes in the top object and uses pointer arithmetic to get the pointer that is below it.
Then inside this function I want to modify the value of the object the secret pointer is pointing to.
In debug I can see the value is being modified just fine in the function but once the function returns the value is not preserved.
I'm beyond confused why.
Any ideas?
Also I own all the memory that these objects and pointers are being created in so I don't think any heap issues should occur as I'm doing my own little memory manager for fun.
I"m thinking the issue is related to me using reinterpret_cast, if I"m right what would be a solution/alternative, and why is this the issue?
void doWork(Obj* pObj) {
// Get address of the object the pointer is pointing to
unsigned char* position = reinterpret_cast<unsigned char*>(pObj);
// 16 Bytes below the object is a secret pointer
position += (sizeof(Obj) + 16);
// Retrieve the secret pointer
Obj* secretObj = reinterpret_cast<Obj*>(position);
// Modify a value in that secret object
secretObj->value += 1;
}
I have tried the suggestions of passing the pointer in by reference and still had no luck.
I'm confused why the way the pointer is passed in would even matter at all honestly as I'm only using that pointer to get the address to use as base then I go and create a new pointer using reinterpret cast with that (address + sizeof(Obj)) and do my work on that newly created pointer.
It's because that you are passing pointer to a pointer.
The address of an address, any changes will be held locally in the scope of function only.
For solving this you should pass the pointer with reference.
void doWork(Obj* &pObj)
This should work.
The (&(*pObj)) is redundant. You are taking the address of an object you just dereferenced. Surely (&(*pObj)) == pObj?
The most likely problem is your offset calculation. Your calculation adds the size of Obj and 16. We cannot tell from your example if this is correct because you don"t give us details of Obj or how the secret pointer is defined. If this calculation is wrong, then the update to value will appear to have worked in your function but you have changed the wrong bytes so it is not seen correctly outside the function.

Method signature C++

Having trouble understanding method signature in C++. Looking for a second opinion.
readPage(File* file, const PageId pageNo, Page*& page) {}
The above can be re-written as follows?
readPage(File *file, const PageId pageNo, Page *&page) {}
So, *file is pointer that is being passed in and *&page is something's address that is then converted to a pointer? I'm confused with the combination of *&
file is a pointer to a File, which means that any changes to what it points to, like
file->doSomething(); // the caller will see this change
will be seen by the calling side, but if one overwrites the pointer, that not only the new value of the pointer not going to be seen by the caller, but any changes to the file after that will also not be observed, because it's a pointer to a different File now, and because the pointer itself is passed by value.
file = new File(); // the caller will not see this change
file->doSomething(); // neither will it see this one
Now, page is a reference to a pointer to a Page. In other words, it behaves like a pointer, so
page->doSomething(); // the caller will see this change
is still observed by the caller. But now if you overwrite the pointer, the caller's pointer will also be changed, and hence all consecutive changes will also be seen:
page = new Page(); // caller also sees this change
page->doSomething(); // and this too
This is because the pointer itself is passed by reference, so any changes to the pointer itself are observed by the calling side.
(and yes, the way you place spaces does not matter, so the two ways you provided are identical)
Page*& is reference to pointer to a Page

c++ - raw pointer to shared_ptr

I'm using box2d and as you already may know, it holds a void* to an object which i can use as reference when collisions occur between different entities. Problem is that the original item is saved inside a shared_ptr since the ownership is unknown and different classes (example player class) can 'equip' another class (weapon).
I'm just wondering if its possible to put this pointer inside a shared_ptr and refer to the same object as the original one?
This is an example:
std::vector<std::shared_ptr<Environment>> listEnvironment;
listEnvironment.push_back(std::make_shared(new Weapon()));
//takes a void pointer
box2d->userId = listEnvironment.back().get();
//some shit happens somewhere else and collision occurs and I get pointer back from box2d's callback:
Environment* envPtr = static_cast<Environment*>(box2d->userId);
As you can see envPtr is going to cause trouble.
Is there a way to refer to the old smart-pointer and increase its reference value?
PS:
In actuality every class creates an box2d body which holds a 'this' pointer so i don't actually have the address to the smart-pointer either. The example above is kind narrowed down to give you a hint of the problem i'm facing.
Best regards
nilo
If Environment has std::enable_shared_from_this<Environment> as a parent class then, yes. Just call envPtr->shared_from_this().

C++ Pointer (Pass By Reference) Question

A pointer that is passed-in-by-reference. Why? aren't pointers just references anyways? What's really happening to this parameter?
void someFunc(MyPtr*& Object)
{
}
Simply speaking, it gives you the ability to change the pointer itself: it can be changed to point to another location in the function.
And the change will be reflected outside.
It enable you to:
void someFunc(MyPtr*& Object)
{
//Modify what Object is pointing to
Object=&old_Object;
//You can also allocate memory, depending on your requirements
Object=new MyPtr;
//Modify the variable Object points to
*Object=another_object;
}
Other's will have to vote to verify this cause I'm a bit rusty on my C++ but I believe the idea here is you'd pass in a pointer by reference, that is instead of creating a new space to store the pointer itself you use a reference to the pointer so if you were to modify the pointer not just the value it would be modified after returning from the function, whereas otherwise all you could do is modify the value at position passed in. Hope that makes sense.
The difference to passing just a pointer is that if the pointer is changed (Object = x) then this change will be seen by the calling function. You could achieve the same when you pass MyPtr** Object and dereference the pointer *Object = x;. With the second approach you could pass NULL to the function. This is not possible for references.
You are not quite right. The pointer content is passed by reference but the pointer itself is still passed by value, i.e. reassinging it to some other pointer will not be reflected upon the exit from the method because the pointer will be set to point to the same memory block as before the call. Think of it as a simple int variable. However with &* or ** you can reassign the pointer and that will be visible outside the scope of this method.
Why?
For the same reason that you would pass in anything else by reference.
aren't pointers just references anyways?
Dear god, no. Not even remotely the same thing. Look, you can try to build a mental model of a reference by starting with a pointer, but by the time you've fixed up all the differences, you have a horrible illogical mess.
References are a much simpler and more intuitive concept, and there are only "historical reasons" for trying to understand pointers before them. Modern C++ uses raw pointers only rarely, and treats them as an implementation detail as much as possible.
A reference is another name for an already-existing thing. That's it. When used as a function parameter, they thus allow the called function to refer to the caller's data.
It also means the pointer can be 0 (NULL) which can having meaning to the method. A reference must always be valid and cannot be made 'nothing'