When to use new-operator? [closed] - c++

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
When should I use the new-operator?
In my example I get the same result using two different methods:
#include <iostream>
int main() {
int *p1;
int n1 = 5;
p1 = &n1;
int *p2;
p2 = new int;
*p2 = 5;
std::cout << *p1 << std::endl;
std::cout << *p2 << std::endl;
return 0;
}

The purpose of using dynamically allocated memory is one (or many) of the following
Run-time control over object's lifetime. E.g. the object is created manually by new and destroyed manually by delete at user's desire.
Run-time control over object's type. E.g. you can deside the actual type of polymorphic object at run-time.
Run-time control over objects' quantity. E.g. you can decide the array size or the number of elements in the list at run-time.
When the object is simply too big to be reasonably placed into any other kind of memory. E.g. a large input-output buffer that is too big to be allocated on stack
In your specific example none of these reasons apply, which means that there's simply no point in using dynamic memory there.

Considering recent C++11 and upcoming C++14 standarts, you should mostly use new operator while programming in languages with garbage collection, such a Java or C#. It is quite natural for these languages. But in modern C++ you can (and mostly always should) avoid allocating memory directly. We have a nice set of smart pointers instead now.

Use new when you want to allocate from the heap, not the stack. Or moving up a level of abstraction. Use new when you need the allocated memory to remain allocated after you the function (more properly scope) in which it is allocated may (in the case of threading) have exited.

You should use new when you wish an object to remain in existence until you delete it. If you do not use new then the object will be destroyed when it goes out of scope.
Some people will say that the use of new decides whether your object is on the heap or the stack, but that is only true of variables declared within functions.
Allocating (and freeing) objects with the use of 'new' is far more expensive than if they are allocated in-place so its use should be restricted to where necessary.

int * p2 = new int;
The new int part tells the program you want some new storage suitable for holding an
operator uses the type to figure out how many bytes are needed.
Then it finds the memory and returns the address. Next, you assign the address to p2, which is
declared to be of type pointer-to-int. Now p2 is the address and *p2 is the value stored
there. Compare this with assigning the address of a variable to a pointer:
int n1;
int * p1 = &n1;
In both cases (p1 and p2), you assign the address of an int to a pointer. In the second
case, you can also access the int by name: p1. In the first case, your only access is via the pointer.
Remember that you should use delete for freeing the memory allocated by new
delete p2;
You need to read some good books ...
I think that "C++ Primer plus" is a good one for you

In this piece of your code you do deal with memory, but with automatic memory. The compiler sorts out for you where to store each variable. you have p1 pointing at n1 but most work was done automatically.
int *p1;
int n1 = 5;
p1 = &n1;ou
However in the next piece of code you request to dynamically allocate an int
int *p2;
p2 = new int;
*p2 = 5;
here you have created a new integer that has been stored dynamically, therefore you should also delete it otherwise you have created your first memory leak. If you allocate dynamically you have to take care you delete it after use.
delete p2;
This is the largest diference when you start to allocate memory using new do delete it otherwise the deconstrucor of an instance of an object will not run and therefore not clear the memory you have allocated.

Related

Regarding dynamic memory allocation in C++

Suppose I have the dynamic memory allocation through p1 as follows,
int* p1 = new int;
*p1 = 1;
I know that the memory referenced by p1 can be freed by using
delete p1;
p1 = nullptr;
But I wonder if there is another pointer p2 pointing at 1, can I delete this pointer in order to free the memory? And what would happen to pointer p1? In addition, what is the relationship between p1 and p2 essentially? For example,
int* p1 = new int;
*p1 = 1;
int* p2 = p1;
// Can I delete p2 like this? And what would happen to p1?
delete p2;
p2 = nullptr;
You can delete p2, but dereferencing p1 will result in undefined behavior, and possible segmentation fault.
It works like this:
Memory is allocated at some address.
Both p1 and p2 pointing to this memory location.
Once p2 deleted - p1 is still pointing to this memory location.
There is no leak, and everything is alright - just don't dereference p1. You can freely do p1 = nullptr, but can't *p1 = 1. Also, you cannot delete p1, since it's deleted already, and you'll probably catch segfault.
you're describing a very known problem in (old) C++ : when several pointers point to the same dynamic memory, which one deletes it?
if you delete both p1 and p2 you double delete the memory, which have undefined behavior (a crash, in the best case), if you delete p1 or p2 and you keep using the memory via the other pointer - you are using dangling pointer, which is undefined behavior (a crash, in the best case).
you need to make sure that when one pointer is deleted - you are not to use that memory in other pointers.
C++11 introduced a standard way of dealing this problem: using a self counting pointer, which only the last pointer deletes the memory:
auto p1 = std::make_shared<int>(0);
auto p2 = p1;
now, the last pointer alive will delete the allocated memory, and you don't have to worry at all who's deleting what.
And what would happen to pointer p1? In addition, what is the relationship between p1 and p2 essentially?
Their essential relationship is that they are pointing to the same address obtained from dynamic memory allocation after the assignment int* p2 = p1;.
So deleting either of them will free the allocated memory. Setting one of them to nullptr won't affect the other though.
So you're left with a dangling pointer that cannot be deleted safely.
You can delete either p1 or p2. There will be no difference. But you should not delete both. Plus once you deleted one you should not use the other. Programmer is responsible for this. The language itself will not provide any help. There are tons of different ways to write bad code here.
There are several techniques/patterns for handling this. Very often smart pointers are used for this. Look at std::shared_ptr documentation. Do not use outdated auto_ptr.
My favorite pattern is "ownership". This means that one pointer "owns" the allocation while all others just use. This requires certain discipline while programming but once this effort is applied, the resulting code is clear and simple. For example:
class MyClass
{
public: ~MyClass() { for(char *p: myStringsDict) delete p; }
private:
std::unordered_set<char*> myStringsDict;
};
Looking at this class it is clear (although it would be nice to add a proper comment) that it owns a dictionary of strings and these strings are valid as long as the instance of this class exists. These pointers can be used in structures that are owned by this class, they can be passed as parameters to functions, etc. It is clear when they should not be used any more.
In server programming when multiple threads are running, double deleting can be very dangerous and difficult to track down. Because after deleting the first pointer the memory becomes free and may be allocated for some other purpose on a different thread. When the second pointer is being freed it may happen that it is deleting a valid allocation while other piece of code has no idea about this and is continuing to use this piece of memory.
Really good solution for all these problems is garbage collection. When explicit allocations are used, programmer needs to apply additional effort in this or that way.
Let's explore the real estate analogy, where memory plays the role of land and pointers are, not-so-surprisingly, act as addresses.
A pointer variable is a yellow post-it note. You can write a street address on it. A variable allocated from the free store is a patch of land at some address.
int *p = new int;
You ask the city to find a small unused patch of land somewhere and assign the title to yourself. You write down its street address on a yellow note.
*p = 1;
You build a neat little house at that address.
int *q = p;
You make a copy of the yellow note. You forget about it for some time.
delete p;
You demolish the building and give up your rights to the patch of land. The city may allocate it to somebody else. Perhaps someone wants to build another small building there, or maybe lay down railway tracks or set up a shark pool. Note this does nothing whatsoever to any of your yellow notes.
p = nullptr;
You wipe a yellow note clean. Your other yellow note lingers on.
*q = 2;
You find the other yellow note, read a streat address off it and assume that land is yours. Bad move. You proceed to build a neat little house on someone else's land. The new owners couldn't care less (they have no way of knowing). Tomorrow they may demolish your building and put their own in place, or overrun you with a train, or perhaps dump 100000 tons of water and 3 makos on you. That's rather unpleasant! Don't touch what's not yours.
when allocating dynamic memory using new it should be freed by delete, as long as you create p1 using new then free it using delete.
you declare p2 as a pointer pointing at the same memory p1 points to then if you want to free memory call delete on p1 not p2 to be readable however that memory can be freed by calling delete on p1 or p2.
if you call delete on p1 then make p2 to point to null in order not to dereference it by mistake because writing:
delete p1;
*p2 = 1;
will cause an undefined behavior.

Is pointer to variable the same as a pointer to an array of one element, or of zero elements?

Array with size 0 Has good explanations of zero-length arrays and is certainly worthwhile and pertinent. I am not seeing it compare zero-length with single-element arrays and with pointer-to-variable.
When I asked before (Is c++ delete equivalent to delete[1]?) I did not express myself well. My question seemed to be the same or included in more general answers about new, new[], delete, and delete[]. Some understood that I was asking only about a single element. All answers in comments seemed correct and consistent.
There is a question that looks like the same as this question. But the body is about using C++ and Java together. Here, we are talking only about C++.
Checking my understanding
I will present pairs of proposed equivalent statements. The statements are declarations or instantiations of a pointer to a single variable followed by a pointer to an array of one element. Then I will state why I would think they are equivalent or not.
Are these pairs equivalent?
int one = 1;
// Sample 1. Same in the sense of pointing to an address somewhere
// whose contents equal one. Also same in the sense of not being able to
// change to point to a different address:
int * const p_int = &one;
int a_int[1] = {1};
// Sample 2.
int * p_int1 = new int;
int * a_int1 = new int[1];
// Sample 3.
delete p_int1;
delete[] a_int1;
// Sample 4. If Sample 3 is an equivalent pair, then (given Sample 2)
// we can write
delete[] p_int1;
delete a_int1;
Granted, Sample 4 is bad practice.
I am thinking: "delete" will call the destructor of the object. delete[] will call the destructor for each element of the array, and then call the destructor for the array. new in Sample 2 would malloc (so to speak) the variable. new[] would malloc an array of one element, then malloc the one element. And then that one element would be set equal to 1. So, I'm thinking THAT'S why I need to call delete[] and not delete when I have an array of even one element. Am I understanding?
And if I am understanding, then calling delete instead of delete[] to free an array of one element, then I will certainly have a memory leak. A memory leak is the specific "bad thing" that will happen.
However, what about this:
int * a_int0 = new int[0];
delete a_int0;
Would THAT result in a memory leak?
I invite corrections of my misuse of terminology and anything else.
Sample 1:
int const * p_int = &one;
int a_int[1] = {1};
NO, these are not equivalent. A pointer is not the same thing as an array. They are not equivalent for the same reason that 1 is not the same as std::vector<int>{1}: a range of one element is not the same thing as one element.
Sample 2:
int * p_int1 = new int;
int * a_int1 = new int[1];
These are sort of equivalent. You have to delete them differently, but otherwise the way you would use p_int1 and a_int1 is the same. You could treat either as a range (ending at p_int1+1 and a_int1+1, respectively).
Sample 3:
delete p_int1;
delete[] a_int1;
These are I suppose equivalent in the sense that both correctly deallocate the respective memory of the two variables.
Sample 4:
delete[] p_int1;
delete a_int1;
These are I suppose equivalent in the sense that both incorrectly deallocate the respective memory of the two variables.
int const * p_int = &one;
int a_int[1] = {1};
They are not equivalent, the first is a pointer to another variable, the other a mere array of size one, initialized straight away with the value one.
Understand this: pointers are entities in themselves, distinct from what they point to. Which is to say, the memory address of your p_int there, is entirely different from the memory address of your variable one. What's now stored in your p_int however, is the memory address of your variable one.
// Sample 2.
int * p_int1 = new int;
int * a_int1 = new int[1];
Here though, they are effectively the same thing in terms of memory allocation. In both cases you create a single int on the heap(new means heap space), and both pointers are immediately assigned the address of those heap allocated ints. The latter shouldn't be used in practice though, even though it's technically not doing anything outright wrong, it's confusing to read for humans as it conveys the notion that there is an array of objects, when there is in reality just one object, ie no arrayment has taken place.
// Sample 3.
delete p_int1;
delete[] a_int1;
Personally, I've never used the "array" delete, but yeah, what you're saying is the right idea: delete[] essentially means "call delete on every element in the array", while regular delete means "delete that one object the pointer points to".
// Sample 4. If Sample 3 is an equivalent pair, then (given Sample 2)
// we can write
delete[] p_int1;
delete a_int1;
Delete on array is undefined according to the standard, which means we don't really know what'll happen. Some compilers may be smart enough to see what you mean is a regular delete and vice versa, or they may not, in any case this is risky behavior, and as you say bad practice.
Edit: I missed your last point. In short, I don't know.
new int[0];
Basically means "allocate space for 0 objects of type int". That of course means 0 * 4, ie 0 bytes. As for memory leaks, what seems intuitive is no, as no memory has been allocated, so if the pointer goes out of scope, there is nothing on the heap anyway. I can't give a more in dept answer than that. My guess is that this is an example of undefined behavior, that doesn't have any consequences at all.
However, memory leaks happen when you do this:
void foo()
{
int* ptr = new int;
}
Notice how no delete is called as the function returns. The pointer ptr itself gets deallocated automatically, since it's located on the stack(IE automatic memory), while the int itself is not. Since heap memory isn't automatically deallocated, that tiny int will no longer be addressable, since you got no pointer to it anymore in your stack. Basically, those 4 bytes of heap memory will be marked as "in use" by the operating system, for as long as the process runs, so it won't be allocated a second time.
Edit2: I need to improve my reading comprehension, didn't notice you did delete the variable. Doesn't change much though: You never have memory leaks when you remember to delete, memory leaks arise when you forget to call delete on heap allocated objects(ie new) prior to return from the scope the pointer to heap memory was located. My example is the simplest one I could think of.
This is a syntax-only answer. I checked this in a debugger with the following code:
// Equivalence Test 1.
*p_int = 2;
p_int[0] = 3;
*a_int = 2;
a_int[0] = 3;
Because I can access and manipulate the declarations as an array or as a pointer to variable, I think the declarations are syntactically equivalent, at least approximately.
I have to apologize
(1) I did not think to define my terms clearly. And it is very hard to talk about anything without my defining my terms. I should have realized and stated that I was thinking syntax and what a typical compiler would probably do. (2) I should have thought of checking in a debugger much earlier.
I think the previous answers are correct semantically. And of course good programming practice would declare an array when an array is the meaning, etc. for a pointer to variable.
I appreciate the attention that has been given to my question. And I hope you can be accepting of my slowness to figure out what I am trying to say and ask.
I figure that the other declarations can be checked out similarly in a debugger to see whether they are syntactically equivalent.
A Compiler's generating the same assembly would show syntactic equivalence. But if the assembly generated differs, then the assembly needs to be studied to see whether each does the same thing or not.

Is dynamic memory allocation be done by pointers [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
dynamic memory allocation by pointers
what is the link between pointers and dynamic memory allocation . why do we use pointers for
dynamic memory allocation . whenever we use new operator we use only pointer variables why?
can anyone explain with an example
According to your question to start with you need not programming but real life example.
Imagine you live in your ordinary flat, it has its own address and on the door you can see big sign "Robin Mandela". It's like static memory allocation. On the start of your program you have some room in memory and a name associated with it. On every vacation you fly to other country where you rent a room in a hotel. You can live one year in one room, another year in another room and even change room during your vacation. You may even not really be interested in what room exactly you will live in, but you need to know that you precisely will have one to live in.
When you ask for dynamic memory allocation, you get some portion of memory. This memory can be allocated almost anywhere, like a room in hotel, and of course you need a key with number to know where to find it. A pointer is like that number on the key - it grants you access to your allocated data.
Also one year you may decide not to go on vacation and rent a room at all. You can't do this with your flat - you have just got it, live there or not. It's like static memory in program.
The size and location (memory address) of objects of automatic and static storage duration is known at compile time. The objects can be accessed through variables and the compiler handles the memory implicitly.
Dynamic memory on the other hand, is allocated at run time, as the name implies. Because it happens at runtime, the compiler can not have knowledge of where the memory is allocated and therefore can not handle the memory for the you. You must access the memory using it's address.
How to get the address of dynamically allocated memory?
It is returned by the new operator which allocates the memory and constructs the object. Since using dynamic memory just in one statement is not useful, you must store the address in a variable.
What type of variable can store a memory address of an object?
A pointer type. The type of the return value of a new-expression is a pointer to the type of object you constructed.
An example:
void foo() {
Foo f; // The object of type Foo has automatic storage and can be accessed through the variable `f`.
Foo* f_ptr; // The pointer object has automatic storage and is not yet initialized.
new Foo; // Bad! The dynamically allocated memory can not be accessed in any way (it has leaked).
f_ptr = new Foo; // The address of another dynamically allocated object is assigned to the f_ptr variable. The object is accessible through this pointer.
delete f_ptr; // Dynamically allocated objects must be deleted explicitly.
// f and f_ptr are destroyed automatically when the scope ends. If the memory pointed by f_ptr was not deleted before this, the memory would leak.
}
The question itself is a bit nonsensical. The keyword new is for allocating memory on the heap and returns either a pointer to the allocated object or throws a std::bad_alloc if allocation fails. It's in a sense like asking why int main(int argc, char** argv) returns an int.
In C++ you have two address spaces to work with; the stack and the heap.
Generally you want to use the heap for allocating your objects and pass them to functions either by reference, the preferred way, or by pointer. In some cases you can't use the stack, mainly when you either don't know how long the object you are creating is going to be alive or when you know that the object should live longer than the scope that creates it. For those cases you should be using std::unique_ptr or std::shared_ptr if you are using C++11 since the object will be deleted automatically when it's no longer needed.
Use of the keyword new is generally discouraged and should only be used when you're certain that neither of the above works.
To read up on the operator new:
cppreference.com
wikipedia
shared_ptr:
cppreference.com
Difference between stack and heap:
learncpp.com
The function you use (for example: malloc() in c) try to get a part of the memory with the length you asked and then it gives you the address of this part of the memory if the allocation was successful else it gives you a 0 (in c and c++ at least).
(When you want to have memory for an array of n items, you must ask for n * item size and you will get the address of the array which is also the address of the first element of your array in fact.)
Example: I want an array of 10 integers
// ask for allocation and get the address of the memory
int * my_array = (int *)malloc(10*sizeof(int));
// you must verify that the allocation was successful
if(my_array != 0) {
// the system gave you the memory you need
// you can do your operations
// " * my_array " and " my_array[0] " have the same meaning
my_array[0] = 22;
* my_array = 22;
// This two lines make the same thing : the put 22 in the memory at the adresse my_array
// same thing for " *(my_array + 9*sizeof(int)) " and " my_array[9] "
my_array[9] = 50;
*(my_array + 9*sizeof(int)) = 50;
// This two lines make the same thing : the put 50 in the memory at the adresse my_array + 36
// 36 = 9*4 (sizeof(int) = 4 in most cases)
free(my_array); //always free the memory to give back the memory to the system and do not "lost it"
}
It is the same in c++ but you replace malloc by new and free by delete. They are keyword but you can see them as functions to understand what it is done.

C++ about dynamic memory [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
What is the difference between:
int myArray[5];
and
int* myArray = new int[5];
int myArray[5] is a bunch of five integers with automatic (or static) storage duration (local memory, often classified as "in stack"). Local memory gets cleared in C++ when the specific scope is exited.
int* myArray = new int[5] is a bunch of five integers on with dynamic storage duration (dynamic memory, often classified as "in heap"). Dynamic memory won't get cleared when the specific scope is exited (myArray has to be an int pointer to store the location of your dynamically created memory).
View the following example:
void foo(){
int myArray[5];
}
void bar(){
int* myArray_dynamic = new int[5];
}
int main(){
foo();
bar();
}
foo will use stack memory, so when foo returns/exits the memory will get freed automatically. However, the dynamic allocated memory, which location is stored in myArray_dynamic in bar won't get freed, as the compiler will only free the memory of myArray_dynamic, not the memory that's stored at its value.
This will create a memory leak, so for every use of new or new[] there has to be a call of delete or delete[] (except you are working with smart pointers, but that's for another question).
The correct version of bar is
void bar(){
int* myArray_dynamic = new int[5];
delete[] myArray_dynamic;
}
The primary reason to pick one or the other is that dynamic allocation is slower, but can be any size (automatic arrays must have a fixed compile-time size), and also that space on the stack is limited, and if you run out, very bad things happen.
The first is an array that's a block of memory allocated either statically or as an automatic variable on the stack during the execution of a function ... it really depends on the context in which its declared/defined.
The second won't compile :-)
To be serious, you really want:
int* myArray = new int[5];
which means we've declared a pointer-type variable that points to an array of integers, and the array of integers is allocated dynamically by the C++ runtime on the heap by the call to new, which is a segment of memory allocated by the OS for your process to dynamically allocate variables in.
The difference is the lifetime.
int myArray[5];
This reserves storage for an array 5 of int. If myArray is declared at block scope, the array is discarded at the end of the block where it is declared.
int* myArray = new int[5];
This dynamically allocates an array 5 of int, the array exists until it is freed with delete [].
What is the difference
One is valid.
The other is not.
In the second you must write
int* myArray = new int[5];
new retuns pointer to the area dynamically allocated in heap.

C++ deleting a pointer to a pointer

So I have a pointer to an array of pointers. If I delete it like this:
delete [] PointerToPointers;
Will that delete all the pointed to pointers as well? If not, do I have to loop over all of the pointers and delete them as well, or is there an easier way to do it? My google-fu doesn't seem to give me any good answers to this question.
(And yeah, I know I need to use a vector. This is one of those "catch up on C++" type assignments in school.)
Yes you have to loop over the pointers, deleting individually.
Reason: What if other code had pointers to the objects in your array? The C++ compiler doesn't know if that's true or not, so you have to be explicit.
For an "easier way," two suggestions: (1) Make a subroutine for this purpose so at least you won't have to write the code more than once. (2) Use the "smart pointer" design paradigm where you hold an array of objects with reference-counters, then the objects are deleted when the objects are no longer referenced by any code.
I agree with Jason Cohen though we can be a bit clearer on the reason for needing to delete your pointers with the loop. For every "new" or dynamic memory allocation there needs to be a "delete" a memory de-allocation. Some times the "delete" can be hidden, as with smartpointers but it is still there.
int main()
{
int *pI = new int;
int *pArr = new int[10];
so far in the code we have allocated two chunks of dynamic memory. The first is just a general int the second is an array of ints.
delete pI;
delete [] pArr;
these delete statements clear the memory that was allocated by the "new"s
int ppArr = new int *[10];
for( int indx = 0; indx < 10; ++indx )
{
ppArr[indx] = new int;
}
This bit of code is doing both of the previous allocations. First we are creating space for our int in a dynamic array. We then need to loop through and allocate an int for each spot in the array.
for( int indx = 0; indx < 10; ++indx )
{
delete ppArr[indx];
}
delete [] ppArr;
Note the order that I allocated this memory and then that I de-allocated it in the reverse order. This is because if we were to do the delete [] ppArr; first we would lose the array that tells us what our other pointers are. That chunk or memory would be given back to the system and so can no longer be reliably read.
int a=0;
int b=1;
int c=2;
ppArr = new int *[3];
ppArr[0] = &a;
ppArr[1] = &b;
ppArr[2] = &c;
This I think should be mentioned as well. Just because you are working with pointers does not mean that the memory those pointers point to was dynamically allocated. That is to say just because you have a pointer doesn't mean it necessarily needs to be delete. The array I created here is dynamically allocated but the pointers point to local instances of ints When we delete this we only need to delete the array.
delete [] ppArr;
return 0;
}
In the end dynamically allocated memory can be tricky and anyway you can wrap it up safely like in a smart pointer or by using stl containers rather then your own can make your life much more pleasant.
See boost pointer container for a container that does the automatic deletion of contained pointers for you, while maintaining a syntax very close to ordinary STL containers.
Pointers are pretty much just memory references and not spiffy little self-cleaning .net objects. Creating proper destructors for each class will make the deletion a little cleaner than massive loops throughout the code.
Let's take a (pseudocoded) real world example .Imagine that you had a class like this:
class Street
{
public:
Street();
~Street();
private:
int HouseNumbers_[];
}
typedef *Street StreetSign;
If you have an array of street signs, and you delete your array of streetsigns, that doesn't mean that you automatically delete the sreets. They re still there, bricks and mortar, they just don't have those signs pointing to them any more. You have got rid of those specific instances of pointers to the streets.
An array of pointers is (conceptually) a bit like an array of integers, it's an array of numbers representing the memory locations of various objects. It isn't the objects themselves.
If you delete[] the array of pointers, all you have done is delete an array of integers.
I think you're going to have to loop over I'm afraid.
I don't know why this was answered so confusingly long.
If you delete the array of pointers, you will free
the memory used for an array of usually ints.
a pointer to an object is an integer containing the adress.
You deleted a bunch of adresses, but no objects.
delete does not care about the content of a memory space,
it calls a destructor(s) and marks the mem as free.
It does not care that it just deleted a bunch of adresses
of objects, it merely sees ints.
That's why you have to cycle through the array first! and call delete
on every element, then you can delete the storage of the array itself.
Well, now my answer got somewhat long... .... strange... ;)
Edit:
Jason's answer is not wrong, it just fails to hit the spot. Neither
the compiler nor anything else in c(++) cares about you deleting stuff that is elsewhere
pointed to. You can just do it. Other program parts trying to use the deleted objects
will segfault on you. But no one will hinder you.
Neither will it be a problem to destroy an array of pointers to objects, when the objects
are referenced elsewhere.