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.
Related
I have a class A like:
class A
{
int a;
}
And, Also I have class B that inherited class A:
class B : public A
{
int b;
public:
static A** ReturnAPtrArray(int size);
}
Then, I make Array having A class Pointer in class B.
A** B::ReturnAPtrArray(int size)
{
A** array = new A*[size];
for(int i = 0; i< size; i++)
{
array[i] = new A();
}
return array;
}
In main func, I Called class B's ReturnAPtrArray() func.
void main(void)
{
int size = 100;
A** aptrArray = B::ReturnAPtrArray(size);
--------Do Something
delete[] aptrArray;
}
This main func makes memory leak. So I deleted every pointers like this:
void main(void)
{
int size = 100;
A** aptrArray = B::ReturnAPtrArray(size);
--------Do Something
for(int i = 0; i< size; i++)
{
delete aptrArray[i];
}
delete[] aptrArray;
}
After modified main func, memory leaks were disappeared.
If I want to free memory, should I delete all pointers in Pointer Array?
Is there any other options?
If I want to free memory, should I delete all pointers in Pointer Array?
Yes you should
delete[] deletes only the array it self.
Since you have a array of pointers you must delete every pointer element individually.
As for other options you can use smart pointers.
Example:
#include <memory>
#include <vector>
int main()
{
std::vector<std::shared_ptr<A>> array;
for(int i = 0; i < 100; i++)
{
array.push_back(std::make_shared<B>());
}
}
when the array goes out of scope it deletes it self
It is important to distinguish between polymorphic-ownership and polymorphic use. Polymorphic ownership is when you want to own a thing (or many things) that are are of an unknown type. Polymorphic use is when you want to manipulate a thing when you don't know what it is. Your example doesn't really make clear why you use inheritance at all, so I will explain both.
If you only create B's just declare them as B's. If you want to pass a set of B's to a function that doesn't know they are B's, the simply create a vector of B's and pass them as pointer-to-A.
Like this ...
std::vector<B> myBs(5); // create 5 default B's
for (const auto& thisB: myBs) Fn(&thisB); // cast a ptr-to-B to a ptr-to-A
Keeping it simple like this will make your life a lot simpler, as this code is type-safe.
If on the other hand you want to own a list of things that might be a B, or might not, but definitely inherits from A. Use something like this.
std::vector<std::unique_ptr<A>> my_maybe_bs_might_not;
This pattern might seem superficially simpler, but it comes with a lot of gotcha's. For example, you must use must use a virtual destuctor. This in turn invokes the rule-of-3/5. Simply put, if the compiler doesn't know a thing is, you have to tell it how it can be moved/copied. If you don't, the compiler will probably do the wrong thing.
A simpler (assuming you have C++17) scheme for polymorphic-ownership is using a variant. When you use a variant, you must list all things it might be, this can include smart pointers.
using MaybeB = std::variant<std::unique_ptr<B>, std::unique_ptr<C>>;
std::vector<MaybeB> my_maybe_bs_might_not;
This pattern allows the compiler to generate all the right code for you, while making it simple to add new classes. The only downside is that because you must list all the things you might want to own. This makes it a bad choice for a library-level system, where the user of the library might want to write their own class (derived from A) and add it to your list.
The general advice is to pick the simplest scheme possible, which in general means avoiding polymorphic ownership unless that is really required.
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)?
So I have a C++ function to which I pass a pointer to a base class, like:
void DoStuffAndAssignPtr(MyBase* ptr)
{
MyBase* p;
//do stuff
if (stuff was awesome) p = new MyAwesome();
else p = new MyBase();
//vftable of p before the return is MyAwesome
(*ptr) = (*p);
}
Now we need to invoke some virtual method that 'MyAwesome' and 'MyBase' implement differently. However, when checking the return value, as below:
void mainly()
{
MyBase* passMe = new MyBase();
DoStuffAndAssignPtr(passMe);
//now passMe is always being returned with MyBase's vftable
}
We can see that 'passMe' is always a 'MyBase' (as far as the vftable shows while debugging in VS). Can anyone provide any guidance as to why this is happening, and how I can ensure that 'passMe' will invoke 'MyAwesome' implementations of virtual methods?
The problem is with the use of (*ptr)=(*p). You should use ptr=p.
Only pointer and reference have polymorphism. When you use dereference (the star *), you lose this property, and only the base part is copied from p to ptr. This is because ptr only have space for that part of information.
You have object slicing issue, below statement slices MyAwesome object to MyBase:
(*ptr) = (*p)
You only pass MyBase* to DoStuffAndAssignPtr and tried to allocate a new pointer which will only overwrite the copy of function parameter. You need to pass the reference of the pointer instead.
void DoStuffAndAssignPtr(MyBase*& ptr);
^^^
Also as passMe is allocated by new outside DoStuffAndAssignPtr already, you created another membory for ptr inside DoStuffAndAssignPtr which will cause memory leak.
A better solution is:
MyBase* MakeAClass()
{
if (stuff was awesome)
{
return new MyAwesome();
}
return new MyBase();
}
int main()
{
MyBase* passMe = MakeBase()
}
I need help with pointers and memory management.
I need to store different objects, all derived from the same base class, and have been using an array to do this but it is causing a segmentation fault when the array is populated with different objects.
My program works fine when the array is full of objects of the same derived type. When the array is populated with different objects it works as it is supposed to through the object stored at the first position but then when it switches to output the second object it gives me the segmentation fault. I know that this is a memory access issue but I am unclear how I'm supposed to manage a variable amount of objects dependent on user input.
thx,
nmr
Make sure the pointers you're pushing on the stack are dynamically allocated. The following will fail:
std::vector<Base*> objects;
void make_one(void)
{
Derived d;
objects.push_back(&d);
}
Because when the function ends, the class pointed to by &d will be deallocated. This is alleviated by dynamically allocating the objects:
std::vector<Base*> objects;
void make_one(void)
{
Derived *d = new Derived;
objects.push_back(d); // a-ok
}
Just remember to go through the vector when you're done, and call delete on them:
struct deleter
{
template <typename T>
void operator()(T* pObject) const
{
delete pObject;
}
}
std::for_each(objects.begin(), objects.end(), deleter());
If you can use boost, there is a pointer container library that will do this for you. Note, you cannot use auto_ptr and try to let it do it for you; auto_ptr's don't play well with containers.
Also, make sure your base classes have virtual destructors:
struct base
{
virtual ~base(void) {} // important!
}
If they are not, calling delete on a base class will run the base constructor only, leaking any resources the derived class might of had. By making it virtual, the compiler can jump to the correct destructor.
I won't post a complete solution because you have identified the question as homework, but I hope I can help you out with the problem a little bit:
Arrays are designed to hold many objects of the same size. The problem with storing different objects in the array (even if they are derived from the same base class) is that the objects are likely to have different sizes.
You're definitely on the right track by thinking about pointers.
edit (in response to comments):
You would be looking at something like this:
BaseClass * array[size];
array[0] = new DerivedClass(...);
array[1] = new OtherDerivedClass(...);
...
A pitfall of this approach would be that there is no built-in deletion of the objects in the array. You would have to loop through and call delete manually:
for (int index = 0; index < size; index++) { delete array[index]; }
It looks very similar to the problem mentioned here: Is array of derived same as array of base? . Are you creating a array of derived objects and trying to access as if it is an array of base?
You can use array of base pointers like this, but note that it is better to use std::vector<Base*> instead of raw arrays:
class Base
{
public:
virtual ~Base(){}
virtual void f() {std::cout<<"Base::f()\n";}
};
class Derived1: public Base
{
public:
~Derived1(){}
void f(){std::cout<<"Derived1::f()\n";}
};
class Derived2: public Base
{
public:
~Derived2(){}
void f(){std::cout<<"Derived2::f()\n";}
};
void print(Base** p, int count)
{
for(int i = 0; i < count; ++i)
{
(*p)->f();
++p;
}
}
int main()
{
Base b;
Derived1 d1;
Derived2 d2;
Base* arr[3];
arr[0] = &b;
arr[1] = &d1;
arr[2] = &d2;
print(arr, 3);
return 0;
};
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) );