Vector of pointer objects creation - c++

I have to implement Vector<MyObject*> by calling AnotherClass::objectCollections(). So here the return type should be Vector<MyObject*>. Also I have to return each MyObject* from another function that could return MyObject*. So that it can populate the Vector. I am newbie for C++ core programming. I want to know the safer way to implement this without crashing, even if the dynamically created vector array is large in number and it will be so helpful if you provide an adequate example or link with the needed return types.

Ok, here is a sample. I fill a vector with a few pointers-to-ints. Then I delete them one by one, and clear the vector at last. If I woudnt manually call delete operator on each element prior to Vector.clear(), there would be leaked memory.
std::vector<int*> Vector;
for (int i = 0; i < 10; i++)
Vector.push_back(new int(i));
std::vector<int*>::const_iterator It;
for (It = Vector.begin(); It != Vector.end(); It++)
{
int* n = *It;
if (n) delete n;
}
Vector.clear();

Related

Push_back method of vector of pointers causes crash C++

I'm trying to add pointers to a vector in C++. As such:
Puzzle * puzzleStart = new Puzzle();
std::vector<Puzzle*> OPEN;
OPEN.push_back(puzzleStart);
The first time a pointer is pushed, there is no problem. The second time, it causes a crash. I'm guessing the issue is the size of the vector, but I don't understand why. Is there anything more to this?
Update: You are right, the problem is elsewhere, I just realized that it occurs while I free the vector of pointer. There is another issue, if the vector contains dupplicates of pointers I think.
if (OPEN.size()!=0){
for (int i = 0; i < OPEN.size(); ++i) {
delete OPEN[i]; // Calls ~object and deallocates *tmp[i]
}
OPEN.clear();
}
How do i make sure that it doesn't try to erase allready deleted pointers?
You are right, the problem is elsewhere, I just realized that it occurs while I free the vector of pointer. There is another issue, if the vector contains dupplicates of pointers I think.
if (OPEN.size()!=0){
for (int i = 0; i < OPEN.size(); ++i) {
delete OPEN[i]; // Calls ~object and deallocates *tmp[i]
}
OPEN.clear();
}
How do i make sure that it doesn't try to erase allready deleted pointers?
If the problem is duplication of pointers, you should consider a container that does not allow duplication, such as a set. E.g.:
std::set<Puzzle*> s;
Puzzle *puzz = new Puzzle();
auto insert_result = s.insert(puzz);
if(!insert_result.second)
{
std::cout << "\"puzz\" was a duplication. No insertion made.\n";
}
// More items inserted into s, and used, etc.
for(auto p : s)
delete p;
s.clear();
When you delete the pointer, set it to nullptr. Deleting a null pointer does not cause a crash.

Destroy pointers to objects in array

Say I want to declare an array of pointers to a specific object like
Object *objects = new Object[size];
and then add some new objects to my dynamically allocated array
for (int i = 0; i < size; i++){
Object* obj = new obj;
objects[i] = *obj;
}
is it enough to deallocate all memory by just calling delete[] on the array, or do I have to loop through the array first and call delete on each object? Or is this stupid to do in practice?
You always have to delete everything you new in some way. That means, you would need to delete obj in every iteration to avoid leaks. Note that you never really store the Object obj points to, but a copy of it.
The way you do it right know is quite unusual and not very handy anyway: The loop you showed does nothing useful since the new Objects[size] already default constructed your Objects. In particular, it does not add any elements, they are already there. You could just leave that out. If you want to change the content of your array, e.g. do more initialization, your loop would usually look more like this
for (int i = 0; i < size; i++){
objects[i] = newValue;
}
Remember, the Objects are already there after new Objects[size]!
In practice, you would be much better of with a
std::vector<Object> objects(size);
(or maybe, if the above does not fit your usecase, a
std::vector<std::unique_ptr<Object>> objects(size);
, but I feel like that is unlikely to be the case). For a good overview of what a std::vector can do and how to use it, read the documentation. Probably most importantly for you: You can index it just like an array.
First, you have to follow the deallocation is reverse order of allocation.
So number of times new that many times delete , similarly number of times new [] that many times delete []
// Assuming objects as array of pointers [ Object **objects ]
for (int i = 0; i < size; i++)
{
delete objects[i] ;
}
delete [] objects;
And your correct allocation should go as:
Object **objects= new Object*[size];
for (int i = 0; i < size; i++) {
objects[i] = new Object;
}
Also , you should use smart pointers std::unique_ptr for hassle free memory management
std::vector< std::unique_ptr<Object> > objects ;
You are storing an array of Objects and not pointers to Object. This means that they won't be deleted when you delete the array and the memory will leak.
If you want to store pointers to Objects in your array then you need to declare it as Object **objects = new Object *[size]; and then you will have to delete all the pointers in the array.
So the better code will look like:
//Allocation:
Object **objects = new Object *[size];
for (int i = 0; i < size; i++){
objects[i] = new Object;
}
//Deletion
for (int i = 0; i < size; i++){
delete objects[i];
}
delete [] objects;
An even better solution would be to use vectors and smart pointers and then you don't need the deletion code at all.
//Allocation:
vector<unique_ptr<Object>> objects;
for (int i = 0; i < size; i++){
objects.push_back(make_unique(new Object));
}
//Deletion
//Hey where did all the code go.

Delete dynamic array of pointers containing duplicates

What's the correct way to free the memory here?
The pointer-array contains duplicates!
class HashTable
{
Bucket<E>** index = new Bucket<E>*[indexSize];
...
}
~ExtHash( )
{
for (size_t i = 0; i < indexSize; ++i)
delete index[i];
delete[] index;
}
I would think hard about whether you want this container to be responsible for deleting the objects; it would be simpler to store them elsewhere, and just use this container to refer to them, not to manage their lifetimes.
Alternatively, you could use std::shared_ptr to manage the objects; then they will be deleted automatically when you've discarded all of them.
If you really want to do it this way, you'll need to remove the duplicates after deleting each one; something like
for (size_t i = 0; i < indexSize; ++i) {
Bucket<E> * victim = index[i];
indexSize = std::remove(index+i+1, index+indexSize, victim) - index;
delete victim;
}
[NOTE: this code may well be wrong; I certainly made a couple of mistakes writing it. If you really want to manage dynamic objects the hard way, then you'll need to test it thoroughly]
Sort index, remove adjacent duplicates with std::unique. O(N log N) and that's as good as it gets.
Use a set to remove duplicates:
std::set<Bucket*> uniqueBuckets(index, index + indexSize);
for(Bucket* bucket: uniqueBuckets)
delete bucket;
In your situation it's dangerous to store raw pointers in such way. Better use std::shared_ptr and just reset shared pointers. And after all pointers will be reseted they will be safely freed.
Perhaps like this:
~ExtHash( )
{
std::sort(index, index + indexSize);
size_t new_end = std::unique(index, index + indexSize) - index;
for (size_t i = 0; i < new_end; ++i)
delete index[i];
delete[] index;
}
Each time you create a pointer, push_back it into a vector. That vector will hold all your created pointers, and will hold each one of them only once.
Later, iterate that vector and delete the pointers.
It's like writing your own simple garbage collector.

Filling an array of pointers, deleting when exiting

In C++, Lets say I'm creating an array of pointers and each element should point to a data type MyType. I want to fill this array in a function fillArPtr(MyType *arPtr[]). Lets also say I can create MyType objects with a function createObject(int x). It works the following way:
MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
Is it the best way to do it? In this program how should I use delete to delete objects created by "new" (or should I use delete at all?)
Since you asked "What is the best way", let me go out on a limb here and suggest a more C++-like alternative. Since your createObject is already returning objects by value, the following should work:
#include <vector>
std::vector<MyType> fillArray()
{
std::vector<MyType> res;
for (size_t i = 0; i != 10; ++i)
res.push_back(createObject(i));
return res;
}
Now you don't need to do any memory management at all, as allocation and clean-up is done by the vector class. Use it like this:
std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]); // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"
Do say if you have a genuine requirement for manual memory management and for pointers, though, but preferably with a usage example.
Your method places the array of pointers on the stack, which is fine. Just thought I'd point out that it's also possible to store your array of pointers on the heap like so. Youd do this if you want your array to persist beyond the current scope
MyType **arptr = new MyType[10];
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
If you do this, don't forget to delete the array itself from the heap
for ( int i = 0 ; i < 10 ; i++ ) {
delete arptr[i];
}
delete [] arptr;
If you're going to use vector, and you know the size of the array beforehand, you should pre-size the array. You'll get much better performance.
vector<MyType*> arr(10);
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
I suggest you look into boost shared_ptr (also in TR1 library)
Much better already:
std::vector<MyType*> vec;
for (int i=0; i<10; i++)
vec.push_back(new MyType(createObject(i));
// do stuff
// cleanup:
while (!vec.empty())
{
delete (vec.back());
vec.pop_back();
}
Shooting for the stars:
typedef boost::shared_ptr<MyType> ptr_t;
std::vector<ptr_t> vec;
for (int i=0; i<10; i++)
vec.push_back(ptr_t(new MyType(createObject(i)));
You would basically go through each element of the array and call delete on it, then set the element to 0 or null.
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
Another way to do this is with an std::vector.
Use an array of auto_ptrs if you don't have to return the array anywhere. As long as you don't make copies of the auto_ptrs, they won't change ownership and they will deallocate their resources upon exiting of the function since its RAII based. It's also part of the standard already, so don't need boost to use it :) They're not useful in most places but this sounds like a good one.
You can delete the allocated objects using delete objPtr. In your case,
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
The rule of thumb to remember is, if you allocate an object using new, you should delete it. If you allocate an array of objects using new[N], then you must delete[] it.
Instead of sticking pointers into a raw array, have a look at std::array or std::vector. If you also use a smart pointer, like std::unique_ptr to hold the objects within an std::array you don't need to worry about deleting them.
typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;
for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
it->reset( new MyType( createObject(i++) ) );
}
You don't need to worry about deleting those when you're done using them.
Is the createObject(int x) function using new to create objects and returning a pointer to this?. In that case, you need to delete that as well because in this statement
new MyType( createObject(i++) )
you're making a copy of the object returned by createObject, but the original is then leaked. If you change createObject also to return an std::unique_ptr<MyType> instead of a raw pointer, you can prevent the leak.
If createObject is creating objects on the stack and returning them by value, the above should work correctly.
If createObject is not using new to create objects, but is creating them on the stack and returning pointers to these, your program is not going to work as you want it to, because the stack object will be destroyed when createObject exits.

creating an array of object pointers C++

I want to create an array that holds pointers to many object, but I don't know in advance the number of objects I'll hold, which means that I need to dynamically allocate memory for the array. I have thought of the next code:
ants = new *Ant[num_ants];
for (i=1;i<num_ants+1;i++)
{
ants[i-1] = new Ant();
}
where ants is defined as Ant **ants; and Ant is a class.
Will it work?
Will it work?
Yes.
However, if possible, you should use a vector:
#include <vector>
std::vector<Ant*> ants;
for (int i = 0; i < num_ants; ++i) {
ants.push_back(new Ant());
}
If you have to use a dynamically allocated array then I would prefer this syntax:
typedef Ant* AntPtr;
AntPtr * ants = new AntPtr[num_ants];
for (int i = 0; i < num_ants; ++i) {
ants[i] = new Ant();
}
But forget all that. The code still isn't any good since it requires manual memory management. To fix that you could to change your code to:
std::vector<std::unique_ptr<Ant>> ants;
for (auto i = 0; i != num_ants; ++i) {
ants.push_back(std::make_unique<Ant>());
}
And best of all would be simply this:
std::vector<Ant> ants(num_ants);
std::vector<Ant> ants(num_ants);
ants.resize(new_num_ants);
Yes that's the general idea. However, there are alternatives. Are you sure you need an array of pointers? An array of objects of class Ant may be sufficient. The you would only need to allocate the array:
Ant *ants = new Ant[num_ants];
In general, you should prefer using std::vector to using an array. A vector can grow as needed, and it will handle the memory management for you.
In the code you have posted, you would have to delete each element of ants in a loop, and then delete the array itself, delete [] ant. Keep in mind the difference between delete and delete [].
One more point, since array indices in C++ are 0-based, the following convention is used to iterate over the elements:
for (i=0; i<num_ants; i++)
{
ants[i] = new Ant();
}
This makes code much more readable.
Do you really need to hold pointers to the items? If you can use objects by value, a far simpler approach is to use a vector: std::vector<Ant> ants(num_ants);. Then not only do you not have to write looping, but you don't have to worry about memory leaks from raw pointers and other object management items.
If you need object pointers to say satisfy an API you can still use vector for the outer container and allocate the objects manually.
struct CreateAnt
{
Ant* operator()() const { return new Ant; }
};
std::vector<Ant*> ants(num_ants); // Create vector with null pointers.
std::generate(ants.begin(), ants.end(), CreateAnt());
std::vector<Ant*> ants( num_ants );
for ( int i = 0; i != num_ants; ++ i ) {
ants[i] = new Ant;
}
Or if you don't know how many in advance:
std::vector<Ant*> ants;
while ( moreAntsNeeded() ) {
ants.push_back( new Ant );
}
On the other hand, I think you need to ask yourself whether
Ant is an entity type or a value. If it's a value, you'll
probably want to skip the pointers and the dynamic allocation;
if it's an entity type, you'll have to consider the lifetime of
the object, and when and where it will be deleted.