I have a simple question that I am not 100% sure on.
Let us say I have a Entity class, that handles objects on the screen. Let us say the Entity class has two float variables, 'x' and 'y' (aka coordinates). Also let us say the entity I am passing has already been declared and is in memory.
I have another class that handles camera movement. It requires an entity to center on. The entity that it is centered on can changed, so I need to use a pointer here I believe. The only thing I do here is grab the X and Y variables when needed. Nothing is changed here.
I've defined it as
void StarField::ChangeFollowEntity(Entity* newFollowEntity) {
followEntity = newFollowEntity;
}
where followEntity is also an Entity class. I would call ChangeFollowEntity(..) to change the entity. Is this actually correct?
I've also seen however this:
void StarField::ChangeFollowEntity(Entity newFollowEntity) {
followEntity = &newFollowEntity;
}
In both cases followEntity is defined as Entity* followEntity; .. What does the second example exactly do here? From what I understand, & would typically be used as a reference type. Maybe it is incorrect to do to begin with.
I am pretty sure I shouldn't be using a reference in this case because the followEntity changes, which references I believe cannot change and must be defined.
So my question is, is my first example correct and the right way to do it? What does the second example do exactly?
In your second version ::
void StarField::ChangeFollowEntity(Entity newFollowEntity) {
followEntity = &newFollowEntity;
}
You pass the newFollowEntity by value, so when your function is called from main or from where ever! A copy of the object is made (using the copy constructor) and sent to the function ChangeFollowEntity, and after the completion of the execution of the function, your followEntity has the address of the COPY of the object, which gets destroyed after the completion of the function call, so your pointer followEntity is left dangling, which is undefined behavior if you access any entity using the followEntity
First is the correct way to do it!!
The second example does the following:
When the function is called a new Entity object newFollowEntiry
is created and whatever is passed into the function is used to
construct it
Then an address of that local stack based object is taken and
assigned to followEntiry to be stored presumably.
When the function execution is complete newFollowEntiry is destroyed
The folowEntity pointer is now pointing at a location in stack where
there is not Entity object anymore.
BUG
What does the second example exactly do here?
Your second example creates a Entity newFollowEntity which only exists for the duration of that function call.
The address of that variable is stored, and then the variable is destroyed, leaving a dangling pointer.
That's bad.
I am pretty sure I shouldn't be using a reference in this case because the followEntity changes, which references I believe cannot change
You can use a reference in this case. A referenced object can be changed - you are probably recalling that a reference cannot be reassigned.
Related
I made the following method in a C++/CLI project:
void GetSessionData(CDROM_TOC_SESSION_DATA& data)
{
auto state = CDROM_TOC_SESSION_DATA{};
// ...
data = state;
}
Then I use it like this in another method:
CDROM_TOC_SESSION_DATA data;
GetSessionData(data);
// do something with data
It does work, returned data is not garbage, however there's something I don't understand.
Question:
C++ is supposed to clean up state when it has exitted its scope, so data is a copy of state, correct ?
And in what exactly it is different from the following you see on many examples:
CDROM_TOC_SESSION_DATA data;
GetSessionData(&data); // signature should be GetSession(CDROM_TOC_SESSION_DATA *data)
Which one makes more sense to use or is the right way ?
Reference:
CDROM_TOC_SESSION_DATA
Using a reference vs a pointer for an out parameter is really more of a matter of style. Both function equally well, but some people feel that the explicit & when calling a function makes it more clear that the function may modify the parameter it was passed.
i.e.
doAThing(someObject);
// It's not clear that doAThing accepts a reference and
// therefore may modify someObject
vs
doAThing(&someObject);
// It's clear that doAThing accepts a pointer and it's
// therefore possible for it to modify someOjbect
Note that 99% of the time the correct way to return a class/struct type is to just return it. i.e.:
MyType getObject()
{
MyType object{};
// ...
return object;
}
Called as
auto obj = getObject();
In the specific case of CDROM_TOC_SESSION_DATA it likely makes sense to use an out parameter, since the class contains a flexible array member. That means that the parameter is almost certainly a reference/pointer to the beginning of some memory buffer that's larger than sizeof(CDROM_TOC_SESSION_DATA), and so must be handled in a somewhat peculiar way.
C++ is supposed to clean up state when it has exitted its scope, so
data is a copy of state, correct ?
In the first example, the statement
data = state
presumably copies the value of state into local variable data, which is a reference to the same object that is identified by data in the caller's scope (because those are the chosen names -- they don't have to match). I say "presumably" because in principle, an overridden assignment operator could do something else entirely. In any library you would actually want to use, you can assume that the assignment operator does something sensible, but it may be important to know the details, so you should check.
The lifetimes of local variables data and state end when the method exits. They will be cleaned up at that point, and no attempt may be made to access them thereafter. None of that affects the caller's data object.
And in what exactly it is different from the following you see on many
examples:
CDROM_TOC_SESSION_DATA data;
GetSessionData(&data);
Not much. Here the caller passes a pointer instead of a reference. GetSessionData must be declared appropriately for that, and its implementation must explicitly dereference the pointer to access the caller's data object, but the general idea is the same for most intents and purposes. Pointer and reference are similar mechanisms for indirect access.
Which one makes more sense to use or is the right way ?
It depends. Passing a reference is generally a bit more idiomatic in C++, and it has the advantage that the method does not have to worry about receiving a null or invalid pointer. On the other hand, passing a pointer is necessary if the function has C linkage, or if you need to accommodate the possibility of receiving a null pointer.
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().
What is a practical example and reason to store a reference to an object instead of a pointer? The obvious reason I can come up with is to avoid memory management.
I've come across a library where sometimes a class will store an object by reference and sometimes by pointer and it's difficult for me to understand why and when to use one over the other?
Example:
class EventBusDemo : public Object
{
private:
HandlerRegistration* playerMoveReg;
};
class PlayerMoveEvent : public Event
{
private:
Player& player; // Why not a pointer here?
};
The key points are that the identity of the object a reference points to can not be changed (its values can though), and a reference can not be null (but you can still get dangling references if you're not careful)
So if you see code like this:
class ObjectWithPointer
{
private:
Object* object;
};
You might need to do this:
void useIt(ObjectWithPointer & value) {
if(value.object!=NULL) {
doSomethingWith(*value.object);
}
}
And you can also do this:
void modifyIt(ObjectWithPointer & value) {
value.object!= some_object_ptr;
}
However if you have this:
class ObjectWithRef
{
private:
Object& object;
};
The first example becomes:
void useIt(ObjectWithRef & value) {
doSomethingWith(value.object);
}
And the a naive conversion of the second
void modifyIt(ObjectWithRef & value) {
value.object=some_object;
}
does something completely different - it copies the value of some_object into the reference, but there is no way to cause the reference to point somewhere else.
The better question is "Why would you use a pointer instead of a reference?". Generally, you should only use a pointer when you can actually answer this question.
For the purposes of referring to something, a pointer requires slightly more cumbersome syntax to use. Also, you can do more with a pointer than you can with a reference, like change where it's pointing, which is a Bad Thing if you aren't actually doing any of that. Any savvy reader who sees your pointer will be forced to consider all sorts of things that they wouldn't do if you had used a reference, like wonder if you remembered to initialized it, or wonder if you change what it's pointing to, et cetera.
It probably impairs compiler optimizations too, since the compiler has to wonder about the same things!
I think it is almost always matter of taste. You can use reference for class members when you want emphasize that one object is not owner of other object or if you want avoid runtime check for null-pointer. Every approach has cons and pros, but in my practice I avoid use reference as object members because you can't reassign their values.
If you see in class X a reference to object rather than pointers, X can be happy to think that the object is local. It is somewhere in the stack. X does not have to think about its destruction definitely. With pointers, the object would be on the heap. Programmer (and especially maintainer of X) might get confused about who would free this pointer. So, peace of mind with references. This point is valid when comparing reference-to-object-on-heap and pointer-to-object-on-stack.
There comes then another problem, dangling references and dangling pointers.
Since, anybody can call a delete on a pointer from any place, it is difficult to find the actual cause of dangling pointers. Not with dangling references. Since, that object would be destroyed when it went out of stack, there is only one place in code where that can happen (it is where that object was created).
So, it is easier to find the problem.
If you get a dangling reference, there is something wrong in design. As you are storing an object Y's reference in X. X is using Y. However, lifetime of X is greater than Y. This can happen when Y is local and X is global. This is counter-intuitive because why would in the stack you would store the reference of upper-stack-object in lower-stack-object.
But with dangling pointers, there can be wrong logic-error or ownership mismatch. So, if problem like dangling reference comes, it can be fixed with better design.
However, if we are storing the object on heap as a reference, it would be difficult to find the dangling-reference problem again.
So, my priority would be :
references to stack object > references to heap object > pointers.
Looking at your code and guessing : EventBusDemo is like some global bus that stores the registration-handler that would be called. Here this is one object and you would be giving it different playerMoveReg over time. So, it is a pointer.
PlayerMoveEvent looks like it would be processed soon as it is an Event. You would create a new PlayerMoveEvent for a new event. So, do you want to make player a pointer or a reference. Do you want to change the player in a event (even by mistake) ? Definitely not. Do you want some piece of mind ? Definitely yes. So, use a reference.
If you use a pointer then:
void PlayerMoveEvent::Foo()
{
// can it be null? its possible because its a pointer!
if (player) player->bar();
}
PlayerMoveEvent::~PlayerMoveEvent()
{
// crash? or memory leak with out?
delete player;
}
A reference makes it clear that it will be valid for the life time of the object (or at least that is the intention) and that you do not own the object. Always use a reference unless a pointer is really required.
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'
I have been teaching myself C++ in the last few days, and have run into some situations that I could use some further explanation on. What is the difference between the following methods besides the obvious class, naming, etc?
void OnTimer(wxTimerEvent &event) ...
void addNPC(Sprite *spr) ...
Are both those methods receiving values passed by reference and doing the same thing? If so, what is the difference? When I first started reading, I saw the method called like this:
addNPC( &sprite );
So I assumed that when you wrote a method that would be receiving a memory pointer, in the method arguments you must write it like you were declaring a memory pointer/location, and not just a value. But then I look at the OnTimer method, and I see that it also has a reference being passed. What's the difference?
Finally, are these two things the same, and just actual coding styles?
void addNPC(Sprite& spr) ...
void addNPC(Sprite &spr) ...
Last question first: the two function prototypes are equivalent. Whitespace is mostly not significant in C or C++.
As for the difference between references and pointers, think of a reference as "syntactic sugar" for a pointer, with the additional restriction that it cannot be NULL. For more on this, see the C++ FAQ: https://isocpp.org/wiki/faq/references
void addNPC(Sprite *spr)
In above code, you need to pass address of Sprite object like below, as it receives pointer.
addNPC( &sprite );
And for the function
void OnTimer(wxTimerEvent &event)
call has to be like below as it takes reference to wxTimerEvent object.
wxTimerEvent evt;
OnTimer(evt);//Passing object by reference.
At calling place, Syntax is same for
both pass by value and pass by
reference.
And for your last question, they both are same, just the coding style difference.
wxTimerEvent &event is a reference to an object. It acts like and looks like a normal variable but it references a variable outside of the function. Any changes made to the local references are actually changing the original. It is essentially a pointer that you can access as a normal variable and it cannot be NULL.
Sprite *spr is a real pointer to an outside variable. Any changes made to it locally are also made outside the function. It can be NULL!
The last two items are identical. Spaces are not significant in C/C++ code.
In addition to other answers there is one feature of const reference - you can assign temporary object to it and object will live as long as const reference is alive.
string its_alive();
void foo() {
const string& some_string = its_alive();
...
}
So you use references if the user of the reference not responsible for object's destruction AND if NULL object makes no sense.
Here's honorary GotW #88 for explanation of const reference to temporary object.