Reputation: 4021
Under C++ I usually ran into an error. Suppose I have the following classes:
class ClassData
{
public:
ClassData() { a=-1; }
public:
int a;
};
class MyClass
{
public:
MyClass() { m_classData = 0; }
MyClass(ClassData* classData) { m_classData = new ClassData(*classData); m_classData->a=1; }
inline bool getClassData(ClassData* classData) {
if (m_classData) { classData = m_classData; return true; }
else return false;
}
private:
ClassData* m_classData;
};
Now in the main I run this test code:
ClassData cdata;
MyClass* m_myClass = new MyClass(&cdata);
int value = 0;
ClassData classData;
if (m_myClass->getClassData(&classData))
value = classData.a;
If the code is run, value
is equal to -1 (instead of 1).
First question: why I've not been able to take a reference to ClassData
in MyClass
? While I'm thinking to have the ClassData
object of m_myClass
(like doing m_myClass->m_classData
if it would be public), in reality I'm calling the member a
on local ClassData
object.
I was thinking that the cause was that I cannot change the local variable address, but if I change the code into this:
ClassData* classData=0;
if (m_myClass->getClassData(classData))
value = classData->a;
I get my program crashing.
Second question: what is the correct way to manage this situation? Is the issue located in the program main function or in how getClassData
is defined giving room for mistakes?
Upvotes: 0
Views: 60
Reputation: 5138
Using values instead of pointers simplifies things and will also remove your memory leak. See live example
#include <iostream>
class ClassData
{
public:
ClassData() { a=-1; }
public:
int a;
};
class MyClass
{
public:
MyClass() { }
explicit
MyClass(ClassData const& classData) {
m_classData = classData;
m_classData.a=1;
}
ClassData const& getClassData() const {
return m_classData;
}
private:
ClassData m_classData;
};
int main()
{
ClassData classData;
MyClass myClass( classData );
classData = myClass.getClassData();
int value = classData.a;
std::cout << value;
}
Upvotes: 0
Reputation: 99094
Here:
bool getClassData(ClassData* classData) {
if (m_classData) { classData = m_classData; return true; }
else return false;
}
Notice that classData
is a local variable. It dies when the function terminates, so the function really does nothing except report whether its m_classData
is null or not.
So in the first case:
ClassData classData; // <-- classData.a is -1
if (m_myClass->getClassData(&classData))
value = classData.a; // <-- classData.a is still -1
In the second case:
ClassData* classData=0; // classData is null
if (m_myClass->getClassData(classData))
value = classData->a; // classData is still null
you dereference a null pointer, which is Undefined Behavior. You're lucky all it does is crash.
A correct (but still unsafe) way to do it is like this:
bool getClassData(ClassData* classData) {
if (m_classData!=0 && classData!=0)
{ classData->a = m_classData->a; return true; }
else return false;
}
I say "still unsafe" because this function cannot really verify that these pointers point to valid data structures. To avoid this danger you must refrain from using pointers so much, and look into references.
Upvotes: 1