Assume we have the following very simple class:
class Item {
public:
Item(){};
virtual ~Item(){};
};
and the class ItemHolder which holds a pointer to an instance of Item. I want ItemHolder to only hold a pointer to the actual data and not copy anything internally. Therefore, I guess this is how ItemHolder should look like:
class ItemHolder {
public:
ItemHolder(){
Q = NULL;
}
ItemHolder(Item &QQ){
Q = &QQ;
}
virtual ~ItemHolder() {
// Don't delete Q!
// The caller is responsible for the fate of Q...
}
private:
Item *Q;
};
However, I guess that this design suffers from certain pathologies which in C++11 are handled with smart pointers. For instance one could expect that the following code would delete a as well, but this is not the case:
Item *a = new Item();
ItemHolder *q = new ItemHolder(*a);
delete q;
What is more, I more often than not meet the following constructor pattern:
ItemHolder(const Item &QQ){
Q = new Item(QQ);
}
accompanied by a destructor like this:
virtual ~ItemHolder() {
if (Q != NULL){
delete Q;
Q = NULL;
}
}
All this may (and will) create ambiguity regarding who is responsible for the memory management of the various objects. What are the commonly employed best practices when it comes to instantiating pointers in C++98 (given that I don't want to create any copies of other variables using new or a copy-constructor)?
Related
Consider a simple class:
class MyInt {
public:
MyInt();
MyInt(const char *num);
};
I want to intergrate reference counting design pattern in to the class, which means i need to keep track of how much pointers point to an instance of this class. I need to implement it in this class only or create a different class and inherit it.
Given this example code i want to clear any allocated memory of the program:
int main() {
MyInt*a = new MyInt("10");
a = new MyInt("20");
delete a;
return 0;
}
My Tries
I tried operator oveloading of '=' and adding referenceCount member:
MyInt &MyInt::operator=(const MyInt* right) {
MyInt*left = this;
*this = right;
left->referenceCount -= 1;
if (left->referenceCount == 0) {
delete (left);
}
return *this;
}
But this does not work because we assign pointer of the class to another pointer.
Also tried to override the new and delete operators but can't seem to make it work and keep track of the number of pointer to an instance.
As it seems i need to implement four things: copy constructor, operator new, operator delete and operator =.
How can i effectivly keep track of the pointers and clear unpointed memory automaticly?
std::shared_ptr does exactly this. From the ref:
Manages the storage of a pointer, providing a limited
garbage-collection facility, possibly sharing that management with
other objects. [...] Once all shared_ptr objects that share ownership
over a pointer have released this ownership, the managed object is
deleted.
so I suggest you use this instead.
a is a pointer, so assigning to a will not involve MyInt::opterator= in any way. There is no way to detect when a pointer to T is assigned to by overloading T's operators. To do this, you would need to design a class type that behaves like a pointer. Then you could properly track when the pointer might leak an object and properly delete it. Fortunately for you, the standard library already provides this class. It's std::shared_ptr. Here is your example modified to use std::shared_ptr :
#include <memory>
struct InfInt {
InfInt(const char *) {}
};
int main()
{
auto a = std::make_shared<InfInt>("10");
a = std::make_shared<InfInt>("20"); // the previous `a` is deleted
// The object pointed to by `a` is automatically deleted when
// the last reference to it goes out of scope
return 0;
}
It should be a simple question, but for the life of me I can't finda solution online.
Simply put, creating an object and adding it to a list of pointers doesn't work for me - as soon as I try access the item in the list in a different method to where it was created, it gives an access violation.
So two questions:
1: What's the best way of doing this?
2: Subsequently, if it's not using pointer lists, what's the best way of removing from the list?
int main( int argc, const char* argv[] )
{
std::list<testClass*> list;
addClass(list);
std::cout << list.front()->a; //item added to list now longer accessible
}
void addClass(std::list<testClass*> list)
{
testClass* c = new testClass();
c->a = 1; c->b = 2;
list.push_back(c); //item still accessible here
}
class testClass
{
public:
int a;
int b;
};
You need to pass your list by reference, you are passing by value here and so it is making a copy of the container and working on that copy:
void addClass(std::list<testClass*> list)
If you modify it like so it should work as you want:
void addClass(std::list<testClass*> &list)
A first macroscopic error is that addClass shold take a std::list<testClass*> & so that it operates on the list contained in main, an not on a local copy.
After that, the entire design has to be better focalized:
Since testClass is not polymorphic (there is nothing virtual in it) what is the point to allocate them dynamically? It will probably be easier to let them contained as value directly in the list itself, havig a std::list<testClass>.
Or ... if you need dynamic allocation, you also have to consider deallocation, or you wil leak memory: if the list cotains pointers, it will destroy the pointer, not what they point-to.
So now, let's follow the two tracks:
Treating objects as values
You need a way to construct a testClass object from given values.
class testClass
{
public:
testClass(int a_, int b_)
:a(a_), b(b_)
{}
int a;
int b;
};
and now you can
void addClass(std::list<testClass>& list)
{
list.emplace_back(1,2);
}
and
int main()
{
std::list<testClass> list;
addClass(list);
std::cout << list.front().a;
}
Note how some * disappered!
Treating objects dinamically
Ok creating with new, but you have to take care of deletion.
One way is delete the pointed from list: just before the } in main...
for(auto p : list) delete p;
this will run across the list and call delete for each of the pointers, thus deallocating (and destroying) the object you allocated with new.
NOTE: This does not make the list empty: the list still contains the pointers, they simply point to invalid address. The pointers will be deallocated by the list at the exit from main
Another way is not to use plain pointers but smart pointer that delete themselves the content when they are destroyed.
This requires an std::list<std::unique_ptr<testClass> > as a container, so that you can
void addClass(std::list<std::unique_ptr<testClass> >& list)
{
list.emplace_back(new testClass(1,2));
}
Now, when main exits, the list gets destroyed with its own elements (the smart pointer) tha in turn will delete the new allocated objects.
In my application I am creating and returning an array filled with dynamically allocated objects from a derived class like this:
void someGetter(std:vector<DerivedClass> & returnV)
{
BaseClass* base = object->clone(); // "object" is a "unique_ptr<BaseClass>"
DerivedClass* derived = dynamic_cast<DerivedClass*> (base);
if (derived != nullptr)
{
returnV.push_back(*derived);
}
else
{
delete base;
}
}
This obviously creates a memory leak (valgrinds helps me here) because derived is never deleted.
I have tried to free the allocated memory like this:
delete &returnV[0];
It doesn't give any compilation errors/warnings and the code still runs fine. but valgrind reports a few additional errors (invalid read, invalid free) on that line of code and the leak is still there.
Is there any way to free the memory returned like this? Or should i return unique_ptr's instead of the objects ?
If you are going to create a vector that holds values of type Derived then the code is correct except for the memory leak. Note that the object you need to free is not the one in the container (which is a copy) but rather the one that you cloned:
void someGetter(std:vector<DerivedClass>& returnV)
{
BaseClass* base = object->clone(); (object is a unique_ptr<BaseClass>)
DerivedClass* derived = dynamic_cast<DerivedClass> (base);
if (derived != nullptr)
{
returnV.push_back(*derived);
}
delete base;
}
Additionally if clone() does what it says (i.e. it clones the object) then you can avoid the operation by first testing with dynamic_cast whether the base object is a DerivedClass. If it is then insert into the container the copy and avoid the cloning.
Simple answer - always delete base.
if (derived != nullptr)
{
returnV.push_back(*derived);
}
delete base;
Vector takes a copy of derived - so clone object is not needed anymore.
[UPDATE]
I hope you have virtual destructor in BaseClass - if not - then add it.
And one more warning: it might happen that base->clone() returns something more derived than derived:
class MoreDerivedClass : public DerivedClass {};
Then this code succeed even if real class of base is MoreDerivedClass:
DerivedClass* derived = dynamic_cast<DerivedClass> (base);
You can use typeid() to check real type of base...
[UPDATE2]
Consider to change a little your design - and keep clones of your base in vector of unique_ptr of DerivedClass:
void someGetter(std:vector<std::unique_ptr<DerivedClass>> & returnV)
{
if (dynamic_cast<DerivedClass*>(base.get()) != nullptr)
{
returnV.push_back(dynamic_cast<DerivedClass*>(base->clone()));
}
}
First off, the design seems very questionable to me: You have at once a polymorphic hierarchy, and also a container that holds values of a specific member of that hierarchy. There's no end to the problems you're inviting. It would seem far more sensible to have a std::vector<std::unique_ptr<Base>>.
Anyway, here's a moderately safe and efficient way to insert into the container only those objects whose dynamic type matches precisely. It assumes that every class in the hierarchy has an accessible copy constructor.
void someGetter(std:vector<DerivedClass> & returnV)
{
if (typeid(*object) != typeid(DerivedClass)) { return; }
returnV.insert(static_cast<DerivedClass&>(*object));
}
The semantics of this are slightly different from yours, because your code would allow the case where *object is of a strictly more derived type than DerivedClass, and the copying into the vector would slice the object. The present code does not suffer from this problem.
Update (after your comment): If DerivedClass is indeed final (and please mark it as such!), then the following does without typeid:
void someGetter(std:vector<DerivedClass> & returnV)
{
if (DerivedClass * p = dynamic_cast<DerivedClass *>(object.get()))
{
assert(typeid(*p) == typeid(DerivedClass)); // beware of slicing!
returnV.insert(*p);
}
}
Yes, push_back uses the copy constructor. I think David is saying that your code should be
void someGetter(std:vector<DerivedClass>& returnV)
{
DerivedClass*derived = dynamic_cast<DerivedClass*>(object.get());
if (derived != nullptr)
returnV.push_back(*derived);
}
avoiding the cloning and deleting altogether.
Note added in edit: We must not pass the pointer obtained from unique_ptr<>.get() on to any function which may potentially keep a copy, defying the whole point of unique_ptr. The above code doesn't do that.
This is a C++ class that I have made with n number of pointers.
class SomeClass
{
private:
int* ptr1;
int* ptr2;
...
int* ptrn;
private:
// constructors, destructors, and methods
};
During the initialization stage, I want to make all those pointers point to NULL (or make pointers point to NULL by default when they are declared) rather than doing so:
void SomeClass::MakePtrNull()
{
ptr1 = NULL;
ptr2 = NULL;
...
ptrn = NULL;
}
Is there any easy method of accomplishing this goal? I'm just wondering if there are any ways of avoiding typing n lines of ptr = NULL; in my function. Thanks in advance.
ADDED based on the answers that I have received so far:
Unfortunately, those pointers have to be separate, as they are used for different purposes. I made the names of the pointers as such just to make a point of what I'm trying to do, but each pointer has a completely different purpose. I guess I would have to make them point to NULL as I have done already. Thanks for your answers.
Instead of int *, create a smart-pointer-like class which works exactly like a int *, but default-constructs with NULL:
template <typename T>
class MyPointer {
T *p;
public:
MyPointer() : p(NULL) { }
MyPointer(T *o) : p(o) { }
operator T*() const { return p; }
// ...and the rest of the traditional smart-pointer operators
};
Then, use it in your class:
class SomeClass
{
private:
MyPointer<int> ptr1;
MyPointer<int> ptr2;
...
MyPointer<int> ptrn;
private:
// constructors, destructors, and methods
};
Every variable of the MyPointer<int> type will be automatically initialized correctly in SomeClass's constructors, without the need for any extra typing. If you did not forget or incorrectly implement any of MyPointer's methods, it will act exactly like a normal pointer, and have the exact same size and performance.
Why don't you use an array or a vector rather than creating n individually named pointers? Then you can do the nulling in a short for loop.
You can do this:
void SomeClass::MakePtrNull()
{
ptr1 = ptr2 = ptr3 = ... = ptrn = NULL;
}
First, the technique that does not work:
Calling memset to set the entire object to zero won't do. First, it'll cause a lot of trouble if your function has one or more virtual functions, and second, a null pointer is not guaranteed to be represented by a bit pattern of all zeros.
What I would probably do in your case is store the pointers in an array or a vector.
Then you can use the std::fill function to set them all to NULL. (Or you could use a loop if you prefer)
Of course, if you need to do this often enough, it may be worth writing a wrapper class which behaves as the pointer, but which sets it to NULL in its default constructor.
Or you could use boost::optional which works essentially like this. (although it is not specific for pointers)
I recommend you to do the following, if you have to keep the pointers separately (probably the most pressing need would be if the pointers can have different types)
class SomeClass {
struct Pointers {
int* ptr1;
int* ptr2;
float* ptrn;
} ptrs;
public:
void MakePtrNull();
};
void SomeClass::MakePtrNull()
{
// clears all pointers at once
ptrs = Pointers();
}
This does work, because value-initialization for classes that doesn't have a user declared constructor will value initialize all its members. Value initialization of a pointer will create a null pointer.
Why not use a default constructor:
SomeClass::SomeClass() : ptr1(NULL), ptr2(NULL), ...
{
}
You could also do:
ptr1 = ptr2 = ptr3 = NULL;
You could put the pointers into a struct and then memset() the struct when needed. The pointers are still separated, but you have the means of targeting them as a single unit without affecting the rest of your class. For example:
struct MyPointers
{
int* ptr1;
int* ptr2;
...
int* ptrn;
};
class SomeClass
{
private:
MyPointers ptrs;
...
};
void SomeClass::MakePtrNull()
{
memset(&ptrs, 0, sizeof(ptrs));
}
Use a vector for this (because by the sounds of it you won't need to ever edit the list in the future - and you need random access). You can do it like this:
class PointerList
{
private:
typedef std::vector<int*> IntPtrVector;
IntPtrVector m_ptrVec;
public:
PointerList()
{
m_ptrVec.reserve(5);
for (int i = 0; i < 5; i++)
m_ptrVec.push_back(NULL);
}
int* getPointer(int index)
{
return m_ptrVec[index];
}
void setPointer(int index, int* ptr)
{
assert(index <= 4);
m_ptrVec[index] = ptr;
}
};
EDIT
Though to be honest this reeks of ghettoness. Are you sure your problem requires this solution? If you elaborate more on your specific problem, in another question perhaps, I'm sure you can get some better answer on how to accomplish what you want more elegantly - rather then by creating a second problem.
I'm searching for a proper way to clean my pointers.
Here the example code:
class Parent {
protected:
int m_Var;
public:
Parent() : m_Var(0) {}
virtual ~Parent() {}
void PubFunc();
};
class Child : public Parent {
protected:
bool m_Bool;
public:
Child() : m_Bool(false) {}
virtual ~Child() {}
void ChildFunc();
};
void RemoveObj(Parent **ppObj)
{
*ppObj->PubFunc();
delete *ppObj;
ppObj = NULL;
}
int main()
{
Parent* pPObj = NULL;
Child* pCObj = NULL;
pPObj = new Parent();
pCObj = new Child();
RemoveObj(&pPObj);
RemoveObj(&pCObj); // This is line 33
return 1;
}
But the compiler gives error:
classes.cpp:33: error: invalid conversion from ‘Child**’ to ‘Parent**’
classes.cpp:33: error: initializing argument 1 of ‘void RemoveObj(Parent**)’
There are soo many ways to handle memory correctly.
The one close to your example would be:
template <typename T>
RemoveObj(T **p)
{
if (p == NULL) return;
delete *p;
*p = NULL;
}
Additionally you might want to use std::auto_ptr instead. It would look like:
int main()
{
std::auto_ptr<Parent*> pPObj(new Parent);
std::auto_ptr<Child*> pCObj(new Child);
// no deletes needed anymore
To put it simple :
Child is a subclass of Parent so that means that Child* can be substituted with Parent*
BUT
Child* is NOT a subclass of Parent* so that means that Child** can't be substituted with Parent**
"Child" and "Child*" are not the same types.
What you need to do is nullify all the pointers to the object you just deleted. The idea of pointers is that there will be more than one pointer storing the address of the same object. If not, there is little reason to use a bare pointer, and so the pattern you're trying to capture is not very useful - but you are far from the first person to try this. As other answers have mentioned, the only way to deal with pointers is to carefully control access to them.
The title of your question is absolutely correct! There's a good reason for it. A pointer identifies a location that stores an object of a specific type. A pointer to a pointer gives you the ability to change what object a pointer points to.
void Foo(Parent **pp)
{
*pp = new OtherChild();
}
Your Child class derives from Parent, and so does my OtherChild class. Suppose the compiler allowed you to do this:
Child *c = 0;
Foo(&c);
You expected that to work, but if it had, then we would now have a Child pointer c that in fact pointers to an instance of OtherChild. Who says those two types are compatible?
Again, this is a very frequent misunderstanding - it crops up repeatedly here for other languages, especially with regard to List<Parent> and List<Child> in C#.
You don't need a wrapper for delete, keep it simple:
int main()
{
Parent* pPObj = NULL;
Child* pCObj = NULL;
pPObj = new Parent();
pCObj = new Child();
delete pPObj;
delete pCObj; // This is line 33
return 1;
}
And remember you will run into issues deleting array type objects with your RemoveObj (since you are always using a scalar delete). An alternative is of course to pass a flag around to indicate you want delete []. But as I said: KISS.
If your problem is dealing with memory and resources, the best advice would be to forget your approach completely and use smart pointers. std::auto_ptr or boost::shared_ptr would be a start point.
If you hold all your heap allocated resources with smart pointers your code will be more robust.
You can find some useful information from the book < C++ common knowledge> Item 8. Pointers to Pointers.
Probably the most simple solution I have found:
#define __REMOVE_OBJ(pObj) RemoveObj(pObj); pObj = NULL;
And just call this one:
__REMOVE_OBJ(pPObj);
__REMOVE_OBJ(pCObj);
But I don't really like it myself...
From discussion on make shared_ptr not use delete
Shared pointer will ensure you cleanup when you should and that you don't access something that is destroyed. Further you can specialise and provide an alternate destruction method.
boost::shared_ptr<T> ptr( new T, std::mem_fun_ref(&T::deleteMe) );