I'm converting a C++ program to C#, but this part has me confused. What does return *this mean?
template< EDemoCommands msgType, typename PB_OBJECT_TYPE >
class CDemoMessagePB : public IDemoMessage, public PB_OBJECT_TYPE
{
(...)
virtual ::google::protobuf::Message& GetProtoMsg() { return *this; }
}
How would it translate into C#?
this means pointer to the object, so *this is an object. So you are returning an object ie, *this returns a reference to the object.
Watch out that if you try to use return *this; on a function whose return type is Type and not Type&, C++ will try to make a copy of the object and then immediately call the destructor, usually not the intended behaviour. So the return type should be a reference as in your example.
In your particular case, you are returning the reference to 'this', since the return type of the function is a reference (&).
Speaking of the size of returned memory, it is the same as
virtual ::google::protobuf::Message* GetProtoMsg() { return this; }
But the usage at call time differs.
At call time, you will call store the return value of the function by something like:
Message& m = GetProtoMsg();
Using a pointer we can directly access the value stored in the variable which it points to. To do this, we simply have to precede the pointer's identifier with an asterisk (*), which acts as dereference operator and that can be literally translated to "value pointed by".
You are just returning a reference to the object. this is a pointer and you are dereferencing it.
It translates to C# return this; in the case that you are not dealing with a primitive.
Like in C# this is an implicit pointer to the object you are currently using.
In your particular case, as you return a reference & to the object, you must use *this if you want to return the object you are currently working on.
Don't forget that a reference takes the variable itself, or in case of a pointer (this), the object pointed to (*this), but not the pointer (this).
Related
I'm quite confused about returning an object from a function. For example:
class A
{
public:
~A(){}
};
A find()
{
...
A a;
return a;
}
Does it return "a" by reference or by value? Moreover, does "find" delete "a" first, then return or return first, then delete "a"?
In your function, you are returning a value, not reference.
A find();
return type is A. Is is value, a copy of a will return.
In order to return a reference, you should write your function as follows.
A& find();
return type A& means a reference to A. But your function body should be change accordingly, in order to return a valid reference.
With the current implementation, you are creating object a inside the function. So it get delete when it goes out of the scope, at the end of function execution.
Your question "Moreover, does "find" delete "a" first, then return or return first, then delete "a"?"
copy of a will return first, then a will delete.
If you return a reference, reference will be return, then object a will get deleted.
In this code you return by value and this is where return value optimization comes(RVO) in to the play. a copy of 'a' is created, then origianal 'a' deleted, return copy of 'a'. The correct sequence is not sure.
The easy part: Does it return "a" by reference or by value?
A find()
{
...
A a;
return a;
}
Returns by value.
The hard part: Moreover, does "find" delete "a" first, then return or return first, then delete "a"?
Technically a copy of a is constructed, a is destroyed and the copy is returned. I cannot find anything in the C++ standard that specifies any particular ordering to those operations, but some are logically implied. Obviously you cannot copy after destruction.
I suspect this is left unspecified to allow C++ implementations to support a wide variety of calling conventions.
Note: This means the returned object must be copy-able. If the copy constructor is deleted or inaccessible, you cannot return by value.
There is no way to be certain of whether the return or the destruction is first. It should not matter and if you are designing a program where it does, give your head a shake.
Caveat
However in practice a modern optimizing compiler will do anything in its power to avoid copying and destroying using a variety of approaches under the blanket name of Return Value Optimization.
Note that this is a rare case where the As-If Rule is allowed to be violated. By skipping the copy construction and destruction, some side effects may not take place.
Also note that even if the need to copy is eliminated, the object must still be copy-able.
Sidenote:
A & find()
{
...
A a;
return a;
}
will return a reference, but this is a very bad idea. a has Automatic storage duration scoped by the function and will be destroyed on return. This leaves the caller with a dangling reference, a reference to a variable that no longer exists.
To get around this,
std::unique_ptr<A> find()
{
...
auto a = std::make_unique<A>();
return a;
}
but you will find that, with a modern compiler, this is no better than returning by value in most cases.
I have to find a possible mistake in the following code. Which could be it ?
cObject * CreateObject()
{
cObject t;
return &t;
}
You are returning the address from stack.
What would the caller of this function do after calling it ?
What is the lifetime of t, and when does it end ?
How would both of these combine with unfortunate consequences ?
t is local to the function, it will die right at the closing brace. The returned pointer can't be used at all, but that's what a caller would probably do, triggering Undefined Behaviour.
you create a temporary object on stack and return a pointer to it. there is no guarantee it will live after the function is finished.
You are returning a point to a local object that does not exist at the end of the function
You're returning a pointer to t, which goes out of scope when you return from the function. You should create a new pointer inside of the function and return that.
cObject *t = new cObject();
return t;
can someone walk through exactly what happens with the memory in this operator overload function? I am confused on how exactly the object created inside the operator function gets deallocated in the main.
Object& operator+(const Object& other) {
Object o(*this); //create instance of o that deep copies first argument
...
//copy contents of other and add onto o
return o;
}
int main() {
Object b;
Object c;
Object a = b + c;
}
Edit: to be more specific, isn't it bad practice to create a local object in a function and then return it by reference? Wouldn't that cause a memory leak?
Edit 2: I am referencing my textbook Data abstraction & problem solving with c++ carrano which suggests an operator + overload for LinkedLists in this format: LinkedList<ItemType>& operator+(const LinkedList<ItemType>& rightHandSide) const;. They implemented the method in the way I described.
Edit 2.5: the full method pseudocode given by the book:
LinkedList<ItemType>& operator+(const LinkedList<ItemType>& rightHandSide) const {
concatList = a new, empty instance of LinkedList
concatList.itemCount = itemCount + rightHandSide.itemCount
leftChain = a copy of the chain of nodes in this list
rightChain = a copy of the chain of nodes in the list rightHandSide
concatList.headPtr = leftChain.headPtr
return concatList
}
Edit 3: Asked my professor about this. Will get to the bottom of this by tomorrow.
Edit 4: The book is wrong.
Returning a reference to a local object
As everyone else correctly states, returning a reference to a local object results in undefined behaviour. You will end up with a handle to a destroyed function-scope object.
Returning references in arithmetic operators
If you think about it, a+b should give you a result, but it shouldn't change a nor b. C++ however leaves it up to you to define how operators work on your own types so it's possible to implement the behaviour you need. This is why the operator+ usually has to create a new object and can't return a reference.
Compound assignments (+=, -=, etc) on the other hand do change the object itself so a += b is changing a. This is why it's usually being implemented by returning a reference (not to a local object, but to the instance itself):
Object& Object::operator+=(const Object& rhs)
{
// do internal arithmetics to add 'rhs' to this instance
return *this; // here we return the reference, but this isn't a local object!
}
It wouldn't cause a memory leak, but o gets destroyed when it goes out of scope, when the function returns. So the reference the caller has is junk. It might appear to work fine for a short time until the memory is overwritten later.
It is simply undefined behavior.
In terms of what happens to memory, the memory will not be reserved to the object after the function returns (because the object is now out of scope).
So it can contain ANYTHING, including the same object by way of coincidence.
In my project, there is a definition of a function call like this.
int32 Map(void * &pMemoryPointer)
In the calling place, the paramenter passed is void*, why cant we just receive it as a pointer itself, instead of this?
Without knowing what the Map function does, I'd guess that it sets the pointer. Therefore it has to be passed by reference.
Using a reference to a pointer, you can allocate memory and assign it to the pointer inside the function. For example
void DoSomething(int*& pointerReference)
{
// Do some stuff...
pointerReference = new int[someSize];
// Do some other stuff...
}
The other way to make functions like that is to return the pointer, but as the Map function in the question returns something else that can't be used.
Reading it backwards, this means that pMemoryPointer is a reference (&) to a pointer (*) to void. This means that whatever pointer you pass gets referenced, and any modification that the function will do to pMemoryPointer will also affect the original (passed) pointer (e.g. changing the value of pMemoryPointer will also change the value of the original pointer).
why cant we just receive it as a pointer itself, instead of this?
That's because by doing that, you are copying the pointer and any change that you'll make to the copy doesn't reflect to the original one.
void im_supposed_to_modify_a_pointer(void* ptr) { // Oh no!
ptr = 0xBADF00D;
}
int* my_ptr = 0xD0GF00D;
im_supposed_to_modify_a_pointer(my_ptr);
ASSERT(my_ptr == 0xBADF00D) // FAIL!
That's a weird function prototype IMHO, but it means
(Update) that the Map function accepts a reference to a void pointer as a parameter.
So I think, it is equivalent to declaring the function like this:
int32 Map(void** pMemoryPointer)
Given the example:
inline string &GetLabel( ) {
return m_Label;
};
Where m_Label is a private class member variable.
The way I think I understand it, this function will return a reference to the variable m_Label. What would be the implications of using this throughout my program and would it be a better to just return the value, instead of the reference? Thank you!
The ampersand isn't before the function name so much as it's after the return type. it returns a reference to a string.
The implication of this is that a caller of this function could modify the value of m_label through the reference. On the other hand, it avoids copying the string. You might want the reference and the function to be const, like so:
inline const string& GetLabel() const
{
return m_Label;
}
Best of both worlds. You avoid the copy, but callers can't change your object.
It returns a reference to the private member.
There are many cases where this is desirable, but some care should be taken.
IMO it's generally not a good idea to return a copy of an internal object that is not an integral type, for overall performance reasons. Yes I know, premature optimization is not good, but this is not really optimization, it's just a good performance practice that allows the caller to determine the performance implications; if it wants a copy, it can just not declare the variable that it's assigning it to as a reference.
There are 2 general rules of thumb I use here:
1) If you don't want the caller to be able to modify the private object directly, declare the return value as a const reference:
inline const string& GetLabel() const{ return m_Label; }
2) A caller should never store the reference returned from a class method, it should only be used locally where the parent object is guaranteed to be in scope.
If for some reason you need callers to be able to store a reference to your internal objects, use smart pointers instead.
Returning a reference means that the calling code can modify the value of your member variable after you return. That's very dangerous, unless you intended for that to happen.
Better is a const reference, or return by value (without the &).
One implication is that if the enclosing object is destructed, the reference becomes invalid:
Object* o = new Object;
string& label = o->GetLabel();
delete o;
// label becomes a dangling reference here.
Another implication is that a caller may modify the string. You can remedy that by returning a const reference.
You're are correct. It's a reference to the string member.
The implication will be that if a caller were to assign a value or otherwise modify the returned string that they would also be modifying the member variable. If this is not the intent you may want to return a copy by value to avoid breaking encapsulation.