Reputation: 151
I mistakenly ended up writing following code. It works on Windows (using VS2010) but not on Mac(GCC).
Can someone describe what is exactly happening on the return type here and why it doesn't work on Mac Release build.
const Mystruct* const & GetMyObject() const
{
return m_pObject;
}
m_pObject is a pointer in this class allocated on heap.
Edited: Above code compiles on Mac. But when I execute following statement it gives me a garbage pointer
Mystruct* pObjectTemp = const_cast<Mystruct*>(GetMyObject());
Upvotes: 1
Views: 176
Reputation: 15872
You are returning a constant-reference to a constant-pointer and then using const_cast
to convert it to a raw pointer. That conversion will not work: http://en.cppreference.com/w/cpp/language/const_cast
const Mystruct* pObjectTemp = t.GetMyObject();
That should return the same pointer you have in your instantiated t
object (note that if t is on the stack, once it goes out of scope, the destructor should be cleaning up it's memory, meaning pObjectTemp will be pointing to memory that is no longer allocated).
You also should modify your function:
const Mystruct* const GetMyObject() const
{
return m_pObject;
}
There is no real benefit to returning a pointer by reference in this case and changing it will prevent the problem Mike mentions here.
Upvotes: 1
Reputation: 254431
Can someone describe what is exactly happening on the return type here
The return type is a reference to a constant pointer to a constant Mystruct
object.
and why it doesn't work on Mac Release build.
You forgot to show the declaration of Mystruct
, but I'll guess that it's a member declared as:
Mystruct* m_pObject;
Note that there is no const
, making it a different pointer type to the const Mystruct*
that the function returns a reference to.
In that case, you're trying to return a reference to the wrong pointer type: const Mystruct*
rather than Mystruct*
. In order to return the correct type, the function must create a temporary pointer of type const Mystruct*
. However, after returning a reference to the temporary, it goes out of scope and may be overwritten with garbage: using the return value gives undefined behaviour.
To fix it, return the pointer by value:
const Mystruct* GetMyObject() const {return m_pObject;}
You might also want a non-constant overload, to avoid the need for the dodgy casting:
Mystruct* GetMyObject() {return m_pObject;}
UPDATE:
To demonstrate that this is indeed the problem (assuming that I'm correct in guessing the type of m_pObject
), consider the following:
#include <iostream>
struct Mystruct {};
struct Test {
Test() : m_pObject(0) {}
const Mystruct * const & GetMyObject() const {
return m_pObject;
}
Mystruct * m_pObject;
};
int main() {
Test test;
std::cout << "MEMBER: " << &test.m_pObject << std::endl;
std::cout << "RETURN: " << &test.GetMyObject() << std::endl;
}
The compiler identifies the problem:
$ g++ test.cpp
test.cpp: In member function ‘const Mystruct* const& Test::GetMyObject() const’:
test.cpp:9:16: warning: returning reference to temporary [enabled by default]
and running it demonstrates that the returned reference does not refer to the member:
$ ./a.out
MEMBER: 0x7fff7a3c4c20
RETURN: 0x7fff7a3c4c08
Upvotes: 1
Reputation: 5168
VS decided to relax the interpretation of const and allowed a variable pointer to be returned. Gcc, being stricter in type checking, did not.
As an aside, code that runs in gcc tends to run on VS, but the reverse is not necessarily the case.
Upvotes: 0