views:

86

answers:

2

Hi

I'm a student writing a method that removes zeros from the end of an array of ints, in c++. The array is in a struct, and the struct also has an int that keeps track of the length of the array.

The method examines each element starting from the last, until it encounters the first non-zero element, and marks that one as the "last element" by changing the value of length. Then the method walks back up to the original "last element", deleting those elements that are not out of bounds (the zeros).

The part that deletes the ith element in the array if i is greater than the updated length of the array, looks like this:

if (i > p->length - 1) {
  delete (p->elems + i); // free ith elem

That line is wrong, though. Delete takes a pointer, yes? So my feeling is that I need to recover the pointer to the array, and then add i to it so that I will have the memory location of the integer I want to delete.

Is my intuition wrong? Is the error subtle? Or, have I got the entirely wrong idea? I've begun to wonder: do I really need to free these primitives? If they were not primitives I would need to, and in that case, how would I?

Thank you!

+3  A: 

If p->elems is a pointer, then so is p->elems + i (assuming the operation is defined, i.e. i is of integral type) - and p->elems + i == &p->elems[i]

Anyhow, you most likely don't want to (and cannot) delete ints from an array of int (be it dynamically or automatically allocated). That is

int* ptr = new int[10];
delete &ptr[5]; // WRONG!

That is simply something you cannot do. However, if the struct contains the length of the array, you could consider the array "resized" after you change the length information contained by the struct - after all, there is no way to tell the size of the array a pointer points to.

If, however your array is an array of pointers to integers (int*[]) and these pointers point to dynamically allocated memory, then yes, you could delete single items and you'd do it along the lines of your code (you are showing so little code it's difficult to be exact).

eq-
+4  A: 

have I got the entirely wrong idea?

I'm afraid so.

If you make one new[] call to allocate an array, then you must make one delete[] call to free it:

int *p = new int[10];
...
delete[] p;

If your array is in a struct, and you make one call to allocate the struct, then you must make one call to free it:

struct Foo {
    int data[10];
};

Foo *foo = new Foo;
...
delete foo;

There is no way to free part of an array.

An int[10] array actually is 10 integers, in a row (that is, 40 bytes of memory on a 32 bit system, perhaps plus overhead). The integer values which are stored in the array occupy that memory - they are not themselves memory allocations, and they do not need to be freed.

All that said, if you want a variable length array:

that's what std::vector is for

#include <vector>
#include <iostream>

struct Foo {
    std::vector<int> vec;
};

int main() {
    Foo foo;

    // no need for a separate length: the current length of the vector is
    std::cout << foo.vec.size() << "\n";

    // change the size of the vector to 10 (fills with 0)
    foo.vec.resize(10);

    // change the size of the vector to 7, discarding the last 3 elements
    foo.vec.resize(7);
}
Steve Jessop