On my work I have met with one bug which can be described as follows.
There are two classes, class A and class B:
class A
{
public:
void print(){}
};
class B
{
A* a;
public:
void init(A* _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
A* a;
B* b;
b->init(a);
// some code .....
delete a; // line 1
a = NULL;
// some code .....
b->PrintWithA(); // line 2
Object "b" doesn't know nothing about state of object "a". In line 1 "a"object has been deleted but on line 2 we continue to use it. When there are a lot of code it is very easy to make such mistake.
My question is the following - which approch to use to avoid some mistakes? I guess I could use observer pattern - but I think it is unjustifiably expensive solution.
Thank's.
You should use a weak ptr (http://en.cppreference.com/w/cpp/memory/weak_ptr)
basically you can provide class B with a weak ptr of A.
whenever comes time to access A, you can try to lock the weak ptr to see if it's still valid.
#include <memory>
class A
{
public:
void print(){}
};
class B
{
std::weak_ptr<A> a;
public:
void init(std::weak_ptr<A> _a) {
a = _a;
}
void PrintWithA()
{
if (auto spt = a.lock()) {
spt->print();
}
}
};
int main()
{
std::shared_ptr<A> a = std::make_shared<A>();
std::unique_ptr<B> b = std::make_unique<B>();
b->init(a);
// some code .....
a = nullptr;
// some code .....
b->PrintWithA(); // line 2
return 0;
}
To guard against that, either B needs to take ownership of the lifetime of A when the object B is constructed, or you need to make A reference counted.
C++11 I think has the concept of a shared pointer which maintains the references and will prevent the object A from being deleted if someone has a reference. See std::shared_ptr
If you are not using C++11 there is boost::shared_ptr which does essentially the same thing. But you need the boost library which I personally prefer not to use, but it's up to you.
Use them like this:
typedef std::shared_ptr<A> A_ptr;
A_ptr a = new A();
class B
{
A_ptr a;
public:
void B(A_ptr _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
Otherwise you could put something together yourself. Something along the lines of:
class A
{
public:
A(){
ref_count = 1;
}
void print(){}
void grab() {
ref_count++;
}
void release() {
ref_count--;
if (ref_count <= 0)
~A();
}
private:
int ref_count;
~A(){
delete this;
}
};
Inside B you'd assign the pointer and call grab();
Rather than call delete (which wouldn't work because it's private) you'd call
a->release() on the pointer.
Now this is not particularly fantastic because you can't use this form:
A a;
So it's not ideal. But if you're using some compiler that doesn't have a shared_ptr and you don't mind the limitation you may use this or a form of it. In general, use shared_ptr.
First of all, the line that says A* a; should probably be A* a = new A;.
In c++ you need to encode this awareness explicitly, it's not done automatically.
One thing you can do is check if _a is NULL inside PrintWithA, but this won't work if you make sure that you always set your pointers to NULL after delete[]ing them (which you've done)
Related
I came across some code I don't understand. In a class B there is a pointer to a method of a different class A but the pointer has no variable. How can I call this method in class B?
This is part of a larger project of someone else, i would like to preserve the existing code.
class A {
public:
A *root() { return this; }
};
class B {
public:
A *root();
};
I expected something like this
A *myA = root();
inside class B to work but i get linker error "undefined reference to ...". The question is more how this construction is called, what is it useful for and how to use it.
As in the comments standing, there is no implementation of B::root(). Maybe the code you have has beside the .h file a .cpp or .hpp file, where the implementation of B::root() stands - or there exists a library with it.
A valid implementation could be A* B::root() { return new A(); }. You can just grep for B::root.
To call B::root(), a simple B b; A* as = b.root(); is enough. Same as with A::root(), where a simple call could be A a; A* as = a.root();
class A {
public:
A *root() { return this; }
};
class B {
public:
A *root();
};
A* B::root() { return new A(); }
int main() {
A a;
B b;
A* asa = a.root();
A* asb = b.root();
return 0;
}
I am a very new programmer and a super beginner so I don't know too much about c++. I had specifically a question regarding making deep copies of pointers. What I have is a class A full of POD's and a pointer to this class (A *P).
I have a second class B which contains some other POD's and a vector of pointers to Class A.
I want to fill this vector of deep copies of A *P because in a loop I will be dynamically allocating and deallocating it. The following does not work. I believe its my copy constructor and overloading of the = operator. This is something I am doing for fun and learning.
class A
{
public:
.....
.....
.....
};
class B
{
public:
B();
~B();
B(const B &Copier);
B& B::operator=(const B &Overloading);
vector<A*> My_Container;
A* Points_a_lot;
int counter;
};
B::B()
{
counter=0;
Points_a_lot=NULL;
}
B::~B()
{
for(size_t i=0; i<My_Container.size(); i++)
{
delete My_Container[i];
}
}
B::B(const B &Overloading)
{
My_Container[counter]=new A(*Overloading.Points_a_lot);
}
B& B::operator=(const B &Overloading)
{
if(!Overloading.My_Container.empty())
{
Overloading.My_Container[counter]=new B(*Overloading.Points_a_lot);
}
return *this;
}
int main()
{ A* p=NULL;
B Alphabet;
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
delete p;
}
return 0;
}
Any help will be great. I thank you for your time. Assume needed libraries included.
Okay, it seems to me that you are very confused about what operator= should be doing. Take a look at this page on operator overloading. This should get you started down the right path for that function.
Second, unrelated to your question check out this question about why your fields (member-variables, what-have-you) should be private.
There are many errors in your code. The main one is that your assignment operator and copy constructor are not deep copying a vector of pointers to A at all, rather, you are trying to put a B* in a location of the vector. What your assignment operator should do is to delete the elements the vector points to, and fill it with deep copies of the elements the source object's vector points to, after checking for self assignment. Your copy constructor should be filled with deep copies of the elements of the source objects.
Second, you should provide a method that adds elements to your class' vector, and let it set the counter variable internally. Having to coordinate both the vector and the counter externally is error-prone and one of the advantages of OOP is to avoid that kind of error. But better still, remove the counter variable altogether. You don't need it. YOur main would then be simplified to this:
int main()
{
B Alphabet;
for(....)
{
A* p = new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.appendElement(p); // B takes ownership, no need to delete in main
}
}
and appendElement could be
class B
{
public:
void appendElement(A* element) { myContainer_.push_back(element); }
// other public methods
private:
std::vector<A*> myContainer_;
};
You could further improve all of this by storing some kind of single ownership smart pointer instead of raw pointers. That would mean you don't have to worry about making deletions yourself. But that is probably beyond the scope of this question.
Now, you should consider avoiding the pointers altogether. In this case, you have to provide no copy constructors, assignment operators or destructors. The compiler-synthesized ones will do just fine. Your class B reduces to
class B
{
public:
void appendElement(const A& element) { myContainer_.push_back(element); }
// other public methods
private:
std::vector<A> myContainer_;
};
I do not fully understand what your requirements are so I attempted to fix the code and do a deep copy of B as that is what it seems you are asking.
#include <vector>
using namespace std;
class A
{
public:
A() : m_someInt(0), m_someFloat(0.0f) {}
// Redundant but putting it here for you to see when it is called (put break-point)
A(const A& a_other)
{
m_someInt = a_other.m_someInt;
m_someFloat = a_other.m_someFloat;
}
int m_someInt;
float m_someFloat;
};
class B
{
public:
B();
~B();
B(const B &Copier);
B& B::operator=(const B &Overloading);
void Cleanup();
void AddA(const A* a);
private:
vector<A*> My_Container;
A* Points_a_lot;
};
B::B()
{
Points_a_lot=NULL;
}
B::~B()
{
Cleanup();
}
B::B(const B &Overloading)
{
// Deep copy B
operator=(Overloading);
}
B& B::operator=(const B &Overloading)
{
// Delete old A's
Cleanup();
// Not using iterators to keep it simple for a beginner
for (size_t i = 0; i < Overloading.My_Container.size(); ++i)
{
// We need new A's which will then copy from the A's in Overloading's container
A* newA = new A( *(Overloading.My_Container[i]) );
// Done with allocation and copy, push_back to our container
My_Container.push_back(newA);
}
return *this;
}
void B::Cleanup()
{
// Assuming B is not responsible for cleaning up Points_a_lot
Points_a_lot = NULL;
for (size_t i = 0; i < My_Container.size(); ++i)
{
delete My_Container[i];
}
// Automatically called when My_Container is destroyed, but here we
// are open to the possibiliy of Cleanup() being called by the client
My_Container.clear();
}
void B::AddA(const A* a)
{
// We are adding a new A. In your code, the incoming A is going to
// be destroyed, therefore, we need to allocate a new A and copy
// the incoming A
A* newA = new A(*a);
My_Container.push_back(newA);
}
int main()
{
A* p=NULL;
B Alphabet;
for(int i = 0; i < 10; ++i)
{
p = new A();
//some stuff example p->Member_of_A=3; etc..
Alphabet.AddA(p);
delete p;
}
// If you put a breakpoint here and step through your code, you will see
// `B` deep-copied
B NewAlphabet = Alphabet;
return 0;
}
A few notes:
Newing and deleteing A in the loop is a bad idea. I realize you are doing this just to learn, which is great, but you may want to keep this in mind. Instead of destroying A through p, allow B to take ownership of the new A
Step through the code by using a debugger to see how it works
Try to post code that is as close to your original as possible when asking "why doesn't this work/compile"
Looks like you should instead have your My_Container consist of unique_ptrs so that when you assign, that the vector takes over ownership of the A instance
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
delete p;
}
so instead declare My_Container as
vector<std::unique_ptr<A*> > My_Container;
then the code will be
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
}
then if you need to do a 'deep copy' create a member in A called clone() or something and return a unique_ptr to the instance, use that when you need to create a copy.
You may want to take a look at boost::ptr_vector. Its interface is very similar to that of a std::vector but it is tailored for pointers and thus:
owns the resources (so no memory leak)
allow polymorphic storage (derived classes)
is const-correct and copy-correct
In order for the copy to work, you'll have to provide a A* new_clone(A const*) implementation.
So I have a class like
class mySafeData
{
public:
void Set( int i )
{
myMutex.lock();
myData = i;
myMutex.unlock();
}
void Get( int& i)
{
myMutex.lock();
i = myData;
myMutex.unlock();
}
private:
int myData;
boost::mutex myMutex;
};
its instance is running. Lets call instance A. I want to create a new class that would take as a start up argument some kind of link to Getter from A and would be capable to somehow save link to thet getter for calling it inside its private methods vhen needed. how to do such thing?
Sounds like you want something like this:
class myOtherData
{
public:
myOtherData(mySafeData& dataSource) :
myDataSource(&dataSource)
{}
private:
// note that if you take the advice in the comments,
// you don't need this wrapper function at all,
// it's simple just to call myDataSource.Get()
int GetData()
{
int result;
myDataSource.Get(result);
return result;
}
mySafeData* myDataSource;
};
mySafeData a;
myOtherData b(a);
// b uses a as its data source (make sure it lives as long!)
I'm not sure what you mean by linc/link. Are you asking for anything more than this pattern?
class Foo {
public:
Foo(mySafeData& d) : data(d) {}
int someFunction() {
int i;
data.get(i);
return i;
}
private:
mySafeData& data;
};
...
Foo f(a);
What's wrong with pointers? Smart, Shared, Scoped... I'll use standard pointers for now.
class B
{
public:
B(mySafeData* ptr) // constructor takes a memory pointer as parameter
:SafeData_ptr(ptr)
{
SafeData_ptr->foo(); // call public function from class A
}
~B() // destructor
{
}
private:
mySafeData* SafeData_ptr; // will hold the mem address of instance A when
// this class is initialized
};
Later on your code, when you have instance A ready, you would do something like this:
B b_demo(&A); // &A passes the memory address of the instantiated object
// and A::foo() will be automatically called when B is constructed.
This is probably not the smartest way to do it, but I think it illustrates the idea.
If I have a pointer to a base class A in C++, how would I be able to tell in my code that the pointer is to a derived class B or C?
Assuming the base class A is polymorphic (i.e. it has at least one virtual function), you can use dynamic_cast. Given an A* ap;:
if (B* bp = dynamic_cast<B*>(ap)) {
// the object is a B
}
else if (C* cp = dynamic_cast<C*>(ap)) {
// the object is a C
}
You generally shouldn't need to know:
struct A {
virtual int generate_foo() = 0;
};
struct B : A {
int generate_foo() { return 42; }
};
struct C : A {
i_;
C(int i) : i_(i) { }
int generate_foo() { return i_++; }
};
If you have an A* you (1) know that it has a generate_foo() method, and (2) know that generate_foo() will generate an appropriate foo for whatever object you really do have. In general that should be enough and you should be able to keep track of when you have an A*.
Philosophically, the designers of C++ spent years trying to avoid adding runtime type information because it' too easily used incorrectly. However, they eventually decided that they were on the wrong end of a losing battle and added dynamic_cast and typeinfo(). C++0x will add more.
Is there a standard way of maintaining a weak pointer to a parent (which is created using a shared pointer) in a child object in C++?
Essentially, I need to implement something on the lines of the following:
Class B;
Class A
{
...
private:
B m_b;
};
Class B
{
....
public:
void SetParentPtr(const boost::shared_ptr<A>& a)
{
m_parentPtr = a;
}
private:
boost::weak_ptr<A> m_parentPtr;
};
In the above all instances of class B need to hold a weak pointer to their parent (i.e object of class A). Class A objects are instantiated using a shared_ptr. I can think of a solution that uses a null deleter. But is that a standard way of doing something like this?
What you are doing above is explicitly supported by weak_ptr and shared_ptr, what happens when you try it? To be more precise, do what you are doing, without the null deleter, and then you use the standard behaviour on the weak_ptr to convert it to a shared_ptr as needed:
boost::shared_ptr<X> it=myWeakPtr.lock();
if (it)
{
// if the conversion succeeded, then the parent instance is still alive
}
There is an implicit conversion to weak_ptr, so you can use
void SetParentPtr(boost::weak_ptr<A> a) { }
directly.
check also boost::shared_from_this so the parent can give a pointer to himself without storing a weak_ptr explicitly.
Otherwise, this seems like a normal way to have a back-pointer. Just check whether there is a real added value in using back-pointers.
I would try to do something like this:
class A
{
A(){};
public:
static boost::shared_ptr<A> Create()
{
boost::shared_ptr<A> newPtr(new A());
newPtr->m_self = newPtr;
return newPtr;
}
// ...
void CreateChild()
{
m_childPtr = B::Create(m_self);
}
private:
boost::shared_ptr<B> m_childPtr;
boost::weak_ptr<A> m_self;
};
class B
{
B(){};
public:
static boost::shared_ptr<B> Create(boost::shared_ptr<A> ptrA)
{
boost::shared_ptr<B> newPtr(new B());
newPtr->m_parentPtr = ptrA;
return newPtr;
}
boost::weak_ptr<A> m_parentPtr;
};