I'm trying to learn about the PIMPL idiom, and c++ in general.
I have a class with a PIMPL style interface, that sets an int value to 7. But, I'm getting a garbage value when I print it, and I don't understand why.
Code
Test.cpp
#include <iostream>
#include "Test.h"
struct Foo::Bar
{
int value;
};
Foo::Foo()
{
Bar tempBar;
myBar = &tempBar;
myBar->value = 7;
}
void Foo::printValue()
{
std::cout << "Value = " << myBar->value << std::endl;
}
int main()
{
Foo myFoo;
myFoo.printValue();
return 0;
}
Test.h
class Foo
{
private:
struct Bar;
Bar* myBar;
public:
Foo();
void printValue();
//~Foo();
};
Output
Value = 2147120498
mybar
is a pointer to a local variable inside the Foo
constructor. When the constructor exits, the variable is gone, but myBar
is still pointing at the old memory.
Since you want to implement PIMPL, there is really only 1 choice. You need to dynamically allocate myBar
using new
, and free it with delete
in the Foo
destructor. You will also have to add a copy constructor and a copy assignment operator to Foo
as well, to avoid leaking memory:
Test.cpp
Foo::Foo()
{
myBar = new Bar;
myBar->value = 7;
}
Foo::Foo(const Foo &src)
{
myBar = new Bar;
*myBar = *(src.myBar);
}
Foo::~Foo()
{
delete myBar;
}
Foo& Foo::operator=(const Foo &rhs)
{
*myBar = *(rhs.myBar);
return *this;
}
Test.h
class Foo
{
private:
struct Bar;
Bar* myBar;
public:
Foo();
Foo(const Foo &src);
~Foo();
void printValue();
Foo& operator=(const Foo &rhs);
};
If you were not implementing PIMPL, then there would be another option. Make myBar
be a non-pointer member of the Foo
class instead:
Test.cpp
Foo::Foo()
{
myBar.value = 7;
}
void Foo::printValue()
{
std::cout << "Value = " << myBar.value << std::endl;
}
Test.h
class Foo
{
private:
struct Bar
{
int value;
};
Bar myBar;
public:
Foo();
void printValue();
};