473,395 Members | 1,556 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Virtual Destructors and array of objects

Ok, my question is not about Virtual destructors and why, but more on
the significance.
Generally we have a virtual destructor in the base class ( and
inadvertently in the derived class) so that you can delete a
derived-class object via a base-class pointer...So, the correct
destructor(s) gets invoked(the derived class one in particular) and the
correct amount of memory is also released.

But if the above is true, why isnt it a good practice to allocate an
array of derived objects via base class pointer and then delete them
via this base class pointer using delete[] ptr ?

I am going through the FAQ about placement new and how the whole thing
is implemented so as to keep track of the number of objects and
therefore call each corresponding destructor.

So if deleting derived objects via base pointer works for one object,
then I dont know why it wouldnt work for deleting an array of derived
objects via base pointer.

Maybe I am missing something or maybe my understanding is not
complete...can anyone throw more light on this.

Thanks.

Jul 23 '05 #1
10 3735

<am******@gmail.com> skrev i en meddelelse
news:11*********************@g49g2000cwa.googlegro ups.com...
Ok, my question is not about Virtual destructors and why, but more on
the significance.
Generally we have a virtual destructor in the base class ( and
inadvertently in the derived class) so that you can delete a
derived-class object via a base-class pointer...So, the correct
destructor(s) gets invoked(the derived class one in particular) and the
correct amount of memory is also released.

But if the above is true, why isnt it a good practice to allocate an
array of derived objects via base class pointer and then delete them
via this base class pointer using delete[] ptr ?

I am going through the FAQ about placement new and how the whole thing
is implemented so as to keep track of the number of objects and
therefore call each corresponding destructor.

So if deleting derived objects via base pointer works for one object,
then I dont know why it wouldnt work for deleting an array of derived
objects via base pointer.
Because the standard says so.

Maybe I am missing something or maybe my understanding is not
complete...can anyone throw more light on this.

Thanks.


See the thread "virtual destructors" in this group. I have given an
explanation as to why it does not work there.

/Peter
Jul 23 '05 #2
am******@gmail.com wrote:
Ok, my question is not about Virtual destructors and why, but more on
the significance.
Generally we have a virtual destructor in the base class ( and
inadvertently in the derived class) so that you can delete a
derived-class object via a base-class pointer...So, the correct
destructor(s) gets invoked(the derived class one in particular) and the
correct amount of memory is also released.
Right.
But if the above is true, why isnt it a good practice to allocate an
array of derived objects via base class pointer and then delete them
via this base class pointer using delete[] ptr ?
I don't seem to understand the question. An array of derived objects
via base class pointer? Could you illustrate it with some code? Do you
mean

base *array = new derived[10];

? That won't work as soon as you try indexing.
I am going through the FAQ about placement new and how the whole thing
is implemented so as to keep track of the number of objects and
therefore call each corresponding destructor.

So if deleting derived objects via base pointer works for one object,
then I dont know why it wouldnt work for deleting an array of derived
objects via base pointer.
Deleting an array involves the _size_. The size is obtained from the
type of the array element...
Maybe I am missing something or maybe my understanding is not
complete...can anyone throw more light on this.


I guess you need to realize the difference between the 'delete' and
'delete[]'. If you need help, just ask (after you've searched all the
usual places for the explanations).

V
Jul 23 '05 #3
On 7 Jun 2005 13:41:37 -0700, am******@gmail.com wrote:

[snip]
why isnt it a good practice to allocate an
array of derived objects via base class pointer and then delete them
via this base class pointer using delete[] ptr ?


You can allocate an array of base class pointers and use them
polymorphically (once you hae allocated their respective objects and
assigned their respective pointers to the array elements, that is).
But delete[] will only delete the storage for the pointers themselves,
not what they point to!

As others have pointed out (and this is, or should be, a FAQ) one must
never allocate an array of *objects* polymorphically because each
array element must have the same size.

--
Bob Hairgrove
No**********@Home.com
Jul 23 '05 #4
> But if the above is true, why isnt it a good practice to allocate an
array of derived objects via base class pointer and then delete them
via this base class pointer using delete[] ptr ? I

don't seem to understand the question. An array of derived objects
via base class pointer? Could you illustrate it with some code? Do
you
mean

base *array = new derived[10];
Lets for simplicity assume that I hold this allocated ptr(via new or clone) via a smart ptr that holds the base type. Whenever I want to process something, I cast it to the type of the correct object and use it. However when the smart ptr goes out of existence it would just do a
delete[] ptr.
? That won't work as soon as you try indexing.this I agree and as I said while processing i cast it to the right
I am going through the FAQ about placement new and how the whole thing
is implemented so as to keep track of the number of objects and
therefore call each corresponding destructor. So if deleting derived objects via base pointer works for one object,
then I dont know why it wouldnt work for deleting an array of derived
objects via base pointer.

Deleting an array involves the _size_. The size is obtained from the
type of the array element...
thats my question. if it knows how to delete one object and it deletes them correctly, then why cant it interpolate over n number of objects.
so lets say
base* ptr = new derived;
delete ptr; //here it does the right thing if the destructor is
declared virtual....it calls the right destrcutor and frees the right
amount of memory.

now when you do
delete[] ptr; //from what I understand, it has to get the ACTUAL size
of the underlying object.

Wouldnt this be analogous to say something like a dynamic_cast
operation from a base class pointer to a derived class pointer. Even in
this case, you need to check the underlying pointer( which is what
operator delete or dynamic_cast does) and just interploate it over n
number of objects( as has been demonstarted in the FAQ via placement
http://www.parashift.com/c++-faq-lit....html#faq-38.8)
Maybe I am missing something or maybe my understanding is not
complete...can anyone throw more light on this.

I guess you need to realize the difference between the 'delete' and
'delete[]'. If you need help, just ask (after you've searched all the
usual places for the explanations).
I probably do understand them as much required within the current context. Thanks.


V

Jul 23 '05 #5
I am actually allocating all objects of the same size, the derived
class. They arent of different sizes(or different types of derived
classes)

Jul 23 '05 #6

<am******@gmail.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...

thats my question. if it knows how to delete one object and it deletes
them correctly, then why cant it interpolate over n number of objects.


The rules are simply different for arrays. A base class pointer can be used
polymorphically. But a pointer to an array of objects cannot.

If you want polymorphic behavior when using an array, then make it an array
of base class pointers, and allocate (and later delete) each pointer in the
array individually. (Even better, use a vector of base class pointers!)

There are plenty of explanations about this behavior in this newsgroup and
the moderated one. Try a google search for something like "delete array
derived class objects".

-Howard
Jul 23 '05 #7

<am******@gmail.com> wrote in message
news:11*********************@g49g2000cwa.googlegro ups.com...
Ok, my question is not about Virtual destructors and why, but more on
the significance.
Generally we have a virtual destructor in the base class ( and
inadvertently in the derived class) so that you can delete a
derived-class object via a base-class pointer...So, the correct
destructor(s) gets invoked(the derived class one in particular) and the
correct amount of memory is also released.

But if the above is true, why isnt it a good practice to allocate an
array of derived objects via base class pointer and then delete them
via this base class pointer using delete[] ptr ?
Because the array is created at compile-time. You need a container that
supports run-time compilation. In effect, the goal is not to delete the
container, but rather, you want to delete the objects within (or in your
case, the objects pointed to). Its the objects, not the container of
pointers, that are polymorphic.

I am going through the FAQ about placement new and how the whole thing
is implemented so as to keep track of the number of objects and
therefore call each corresponding destructor.

So if deleting derived objects via base pointer works for one object,
then I dont know why it wouldnt work for deleting an array of derived
objects via base pointer.
There is a huge difference since a base pointer to an object is potentially
a derivative. An array knows no derivatives (its a compile time creature).
Thats why vectors, deques, stacks, list, map, sets where created. So that
the object, not the container, has invocable and callable behaviours.

Maybe I am missing something or maybe my understanding is not
complete...can anyone throw more light on this.


You are on the right track.

Jul 23 '05 #8

<am******@gmail.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
I am actually allocating all objects of the same size, the derived
class. They arent of different sizes(or different types of derived
classes)


No you are not, you are allocating objects but storing pointers. the array
is not an array of objects. If you delete the array, you only delete the
object's pointers. In fact, the same goes for any type of container:

#include <iostream>
#include <vector>

class Base
{
int m_b;
public:
Base(int n) : m_b(n) { std::cout << "Base ctor\n"; }
virtual ~Base() { std::cout << "\nBase d~tor"; }
};

class Derived : public Base
{
public:
Derived(int n) : Base(n) { std::cout << "Derived ctor\n"; }
~Derived() { std::cout << "\nDerived d~tor"; }
};
int main(int argc, char* argv[])
{
std::vector< Base* > v_ptr_bases;

for (int i = 0; i < 5; ++i)
{
v_ptr_bases.push_back(new Derived(i));
}

// v_ptr_bases.clear(); // no way, those are pointers

typedef std::vector< Base* >::iterator VIter;
for (VIter it = v_ptr_bases.begin(); it != v_ptr_bases.end(); ++it)
{
delete *it;
}

return 0;
}

/*
Base ctor
Derived ctor
Base ctor
Derived ctor
Base ctor
Derived ctor
Base ctor
Derived ctor
Base ctor
Derived ctor

Derived d~tor
Base d~tor
Derived d~tor
Base d~tor
Derived d~tor
Base d~tor
Derived d~tor
Base d~tor
Derived d~tor
Base d~tor
*/

There is no doubt that an auto pointer saves the day since manual
deallocation is no longer needed. But its still relevant to acknowledge that
a container of pointers is not a container of objects.

Jul 23 '05 #9
Peter Julian wrote:
There is no doubt that an auto pointer saves the day since manual
deallocation is no longer needed. But its still relevant to acknowledge that
a container of pointers is not a container of objects.


I'm not sure if you were suggesting this or not, but it is worth noting
that std::auto_ptr does NOT meet the requirements to be stored in any of
the standard containers.
Jul 23 '05 #10
Me
The important thing to know is that C++ is a value based language, it
doesn't behave like other languages where you can do this (all their
objects are really pointers to objects, they just hide that from you):

struct A { int a; };

struct B : A { float f; };

vector<A> v;
B b;

//vector<A>::push_back(const A &);
v.push_back(b);

^-- What happens here is called slicing. In the call to push_back, b
gets downcasted to an A object and just copies the A object of b over
to the end of the vector. Slicing is considered to be a bad thing in
all but a few cases as you lose certain information. Agree with me so
far?

A a;
//A::operator=(const A &);
a = b;

^-- Slicing also happens with regular objects because that's what the
regular assignment operator is expected to look like.

A arr[10];
//arr's index operator returns an A &, this calls the assignment
operator above
arr[2] = b;

A *narr = new A[10];
//ditto
narr[2] = b;

^-- Slicing also happens when using plain arrays of regular objects. So
you can see there is no way to store a full B into an array of A,
therefore an array of type A can only hold objects of type A (or a
const/volatile compatible A).

The standard doesn't want to bend over backwards to handle the rare
case of where you write a correct assignment operator that somehow
handles slicing because doing that requires the base and derived class
to be the same size (rare in general and not guaranteed) and in your
case, involves a memcpy to copy the vtable over (which is undefined and
assumes your implementation even uses vtables).

Not all is lost, this code is correct, see if you can figure out why:

vector<A*> v2();

// this is ok
v2.push_back(new B);
delete v2[0]; // call's B's destructor

// this is ok
A **arr2 = new A*[1];
arr2[0] = new B;
delete arr2[0] // calls B's destructor
delete [] arr2;

Jul 23 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Jimmy Johns | last post by:
Hi all, I have some class hierarchy as follows: class S {}; class A {}; class B {public: vector<S*> v_; virtual ~B();}; class C : public virtual A, public virtual B { // do I need to define...
39
by: Ele | last post by:
Is it correct to say that Whenever a class has a virtual member function, define its destructor as "virtual"? Can a destructor as "pure virtual"? When is it needed to do so? For an interface,...
2
by: Chunhui Han | last post by:
Hi, I was recently reading about virtual base classes in C++. The book I was reading says that it is illegal to have non-virtual destructor for the virtual base class. It seems to me that...
23
by: heted7 | last post by:
Hi, Most of the books on C++ say something like this: "A virtual destructor should be defined if the class contains at least one virtual member function." My question is: why is it only for...
11
by: santosh | last post by:
Hello, I was going through the Marshal Cline's C++ FAQ-Lite. I have a doubt regarding section 33.10. Here he is declaring a pure virtual destructor in the base class. And again defining...
4
by: Tony Johansson | last post by:
Hello Experts!! Assume I have a base class called animal. I want this class to be abstract so I make the destructor pure virtual by having this statement. virtual ~Animal() = 0; Destructor...
7
by: Christian Christmann | last post by:
Hi, should destructors of a base class be always declared as "virtual" in order to avoid "partially destroying"objects when a derived class object is deleted through a pointer to a base class? ...
7
by: eric | last post by:
hello i'm confused by an example in the book "Effective C++ Third Edition" and would be grateful for some help. here's the code: class Person { public: Person(); virtual ~Person(); // see...
7
by: Markus Svilans | last post by:
Hello, My question involves virtual functions and inheritance. Suppose we have a class structure, that consists of "data" classes, and "processor" classes. The data classes are derived from...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.