0

So I've got to do a project, where I need to implement an array, a list, binary heap, binary tree and a red-black treeand then measure their performance, compare them and draw some conclusions. Now, the rules are like this:

  1. Got to use C/C++
  2. Cannot use std:: (only cout, maybe a string), Boost

So I am on a first step, implementing an array. It looks like this:

array.h

#pragma once
#include <iostream>
class array
{
    int elements;
    int *table;
public:
    array();
    array(int *t, int n);
    int size() const;
    int *get() const;
};

array.cpp

#include "array.h"    

array::array(int *t, int n) : elements(n), table(new int[elements])
{   
    memcpy(table, t, elements * sizeof(int));
}

int array::size() const
{
    return elements;
}

int *array::get() const
{
    return table;
}

The program basically has a menu-like structure, using simple switch and 5 different menus for 5 conteners. Now, I have to implement deleting/adding elements, printing out the array, etc. I have a code that will print out the array in one line:

int *p = myArray.get();
int s = myArray.size();
std::cout << "[";
for (int i = 0; i < myArray.size(); i++)
{
    if (s - i == 1) std::cout << *(p + i) << "]" << '\n';
    else std::cout << *(p + i) << ", ";
}
delete p;

The thing I am curious about is the last line I wrote. Firstly I didn't use delete, cuz nowhere in this block of code exists a new operator. But then I thought, yeah well, it prolly causes memory leaks, and I've added that line. Works both ways. And my question is: Which one is correct? In this situation do I have or should I delete a pointer?

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
minecraftplayer1234
  • 2,127
  • 4
  • 27
  • 57

3 Answers3

5

Any time you use new (or new[]), you need a matching delete (or delete[]), so you need to delete the array pointed to by array::table somewhere. array's destructor is the usual place to do it, since array owns that data. That way your array's data will be deleted whenever the array goes out of scope. Keep in mind the rule of three though. If your class owns some resource, you should override the default copy constructor, copy operator, and destructor.

You seem to misunderstand what delete does. delete deletes dynamically allocated objects, not pointers. After doing int *p = myArray.get();, you have the following situation:

+-----------+
|  myArray  |
| +-------+ |  +-------+
| | table | |  | p     |
| +---+---+ |  +-------+
+-----|-----+  |
      | +------+
      | |
     +v-v-----------------------+
     |       allocated data     |
     +--------------------------+

When you call delete[] table or delete[] p, you'll end up with the following:

+-----------+
|  myArray  |
| +-------+ |  +-------+
| | table | |  | p     |
| +---+---+ |  +-------+
+-----|-----+  |
      | +------+
      | |
      v v

      Nothing here anymore, but the pointers still point here.

The array pointed to by both myArray.table and p is gone, so the behavior when calling delete[] on a pointer that points to the memory that used to hold that array is undefined.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
3

'Deleting' a pointer will free the memory that it points to regardless if it is a copy or the 'original'. This is because it simply holds a memory address (or a copy of the memory address) and not the actual memory.

Also when you access freed memory you can't guarantee that the data that is returned to you is the data you wanted/expected, so you should only do delete pointers in the destructor of their owner or when you are sure that you won't need them anymore.

And you when using new or new[] you should always use the correct delete or delete[] counterpart.

mvrma
  • 143
  • 1
  • 9
0

You may consider the ownership of your dynamic resource.

The ownership means someone has responsibility to free it when no one will use it anymore. If your array create the resource, you better let it free it by his own in destructor. The one created the resource be the owner naturally.

If you intend to let someone outside get the pointer, the int* p, and free it, delete p(should be delete [] p), that is you give the ownership to p. Your array need to know it does not own it anymore, and not allowed to delete it by array.

When the ownership is clearly explicit, the resource will have less chance to be leaked or double deleted.

BTW, here are some tips for your code.

  • p = new T pair with delete p; p = new T[] pair with delete p []
  • Prefer use size_t to represent count of element.
  • Passing int* t can have the constness like const int* t. It does not need t be mutable .
Chen OT
  • 3,486
  • 2
  • 24
  • 46