开发者

Delete operator and arrays?

I have an abstract Base class and Derived class.

int main ()
{
  Base *arrayPtr[3];

  for (int i = 0; i < 3; i++)
  {
    arrayPtr[i] = new Derived();
  }

  //some functions here

  delete[] arrayPtr;

  return 0;
}

I'm not sure how to use the delete operator. If I delete ar开发者_开发百科ray of base class pointers as shown above, will this call derived class objects destructors and clean the memory?


You have to iterate over the elements of your array, delete each of them. Then call delete [] on the array if it has been allocated dynamically using new[].

In your sample code, the array is allocated on the stack so you must not call delete [] on it.

Also make sure your Base class has a virtual destructor.

Reference: When should my destructor be virtual.


No, you have to explicitly delete each item in the array:

for (int i = 0; i < 3; ++i)
{
    delete arrayPtr[i];
}


You should instead do:

 for ( int = i; i < 3; i++ )
 {
    delete arrayPtr[i];
 }

And you shouldn't do delete[] arrayPtr; as you're trying to free/delete a stack allocated arrayPtr.

Another thing to consider is using a std::vector of pointers instead of an array. And if you're using a compiler that implements TR1, you could also use a std::vector of std::tr1::shared_ptr instead of raw pointers, and than you wouldn't need to worry about deleting those objects yourself.

Example:

{
    std::vector< std::tr1::shared_ptr<Base> > objects;
    for (int i=0; i < 3; ++i)
    {
        objects.push_back(std::tr1::shared_ptr<Base>(new Derived()));
    }
}  // here, once "objects" exit scope, all of your Derived objects are nicely deleted


You have to delete the members of the array individually. You must also make sure that your base class has a virtual destructor. You might also want to consider making it an array (or better still a std::vector) of smart pointers, such as boost::shared_ptr.


No, you can not do that. As others suggested you have to go through each item and delete it. It's a very simple rule to remember. If you allocated using new then use delete, and if you had used new[] then use delete[]


Notice what's absent:

int main() {
  boost::ptr_vector<Base> v;
  for (int i = 0; i < 3; i++) v.push_back(new Derived());
  // some functions here, using v[0] through v[2]
}

Check Boost's pointer containers out.


Operator delete must match operator new on that pointer, if it was allocated with new[], you must call delete[] and vice versa;

int* pInt = new int;
delete pInt; OK
delete [] pInt; WRONG

int[] pIntArr = new int[3];
delete [] pIntArr; OK
delete pIntArr; WRONG

In your case there is something else wrong - you are trying to delete that was allocated on the stack. That wouldn't work.

You must delete each pointer individually in this particular case.


What you have there is undefined behaviour -- a bug. Each call to new needs to be matched with a delete; each call to new[] needs to be matched with a delete[]. The two are separate and can't be mixed.

In the code you posted, you have an array of pointers to Base allocated on the stack. You're then calling delete[] on an array allocated on the stack -- you can't do that. You can only delete[] an array allocated on the heap with new[].

You need a call to delete for each element allocated with new -- or preferably, look into using a container class, such as std::vector, instead of using an array.


Make sure Base has a virtual destructor. Then like fretje outlined, delete each element in the array, then delete the array.

You should be using std::vector for the array. That said, you should really be using a container made for this sort of thing. (So you don't accidentally fail to delete all the elements, which will definitely be the case if an exception gets thrown!) Boost has such a library.


You're mixing paradigms -- The array delete operator is designed to free memory allocated by the array new operator, but you're allocating your array on the stack as an array of pointers and then allocating an object for each array member. In your code, you need to iterate through the array.

To use the array new operator, you'd declare like this:

Base *array;
array = new Base[3];
/* do stuff */
delete[] array;

This allocates a contiguous memory area for the three objects -- note that you've got an array of Base objects, not an array of pointers to Base objects.


No, this doesn't quite do what you want.

There are two points to watch out for here:

  1. The syntax delete[] arrayPtr is used if you dynamically allocate the array, like this:

    arrayPtr = new (Base *)[mylength];
    

    In your case, however, you have a statically allocated array, so there is no need to delete it. You do, however, need to delete the individual elements in the array:

    for ( int = i; i < 3; i++ )
         delete arrayPtr[i];
    
  2. The second point you need to take care of is to make the destructor of the class Base virtual:

    class Base
    {
        virtual ~Base();
        /* ... */
    };
    

    This ensures that when you call delete on a Base * that is actually pointing to a Derived, the destructor of Derived is called, not just the destructor of Base.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜