473,765 Members | 2,065 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

delete [] of Derived objects through Base object which has virtualdtor

Suppose

class Base
{
public:
virtual ~Test() { ... }
// ...
};

class Derived : public Base
{
public:
virtual ~Derived() { ... }
// ...
};

int main()
{
Base* base_ptr = new Derived[10]();
delete [] base_ptr;
return EXIT_SUCCESS;
}

If the Base class dtor is not not virtual, 'delete [] base_ptr' has
undefined behaviour.

Will 'delete [] base_ptr' call each Derived class dtor because the
Base::~Base() is virtual ? Is the deletion in the above code valid ?.
Or does this also invoke undefined behaviour ?

Kindly clarify.

Thanks
V.Subramanian
Jun 27 '08 #1
12 2722
Sam
su************* *@yahoo.com, India writes:
Suppose

class Base
{
public:
virtual ~Test() { ... }
// ...
};
No, we can't suppose that. This is not a valid C++ class definition.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBIFprDx9p 3GYHlUOIRAoPKAJ 4wfi5RLzo/ysrMPMMYrWm49EV AEQCffZbw
HqpoXHjs6UC/qKzu2a8t+pc=
=Jpso
-----END PGP SIGNATURE-----

Jun 27 '08 #2
su************* *@yahoo.com wrote:
Suppose

class Base
{
public:
virtual ~Test() { ... }
Did you mean
virtual ~Base() { /*...*/ }
here?
// ...
};

class Derived : public Base
{
public:
virtual ~Derived() { ... }
// ...
};

int main()
{
Base* base_ptr = new Derived[10]();
delete [] base_ptr;
return EXIT_SUCCESS;
}

If the Base class dtor is not not virtual, 'delete [] base_ptr' has
undefined behaviour.

Will 'delete [] base_ptr' call each Derived class dtor because the
Base::~Base() is virtual ? Is the deletion in the above code valid ?.
Or does this also invoke undefined behaviour ?
If Base is correct with a proper virtual Base destructor (and not Test
destructor which is invalid) I believe this is well formed code.

--
Jim Langston
ta*******@rocke tmail.com
Jun 27 '08 #3
Jim Langston wrote:
su************* *@yahoo.com wrote:
>Suppose

class Base
{
public:
virtual ~Test() { ... }

Did you mean
virtual ~Base() { /*...*/ }
here?
>// ...
};

class Derived : public Base
{
public:
virtual ~Derived() { ... }
// ...
};

int main()
{
Base* base_ptr = new Derived[10]();
delete [] base_ptr;
return EXIT_SUCCESS;
}

If the Base class dtor is not not virtual, 'delete [] base_ptr' has
undefined behaviour.

Will 'delete [] base_ptr' call each Derived class dtor because the
Base::~Base( ) is virtual ? Is the deletion in the above code valid ?.
Or does this also invoke undefined behaviour ?

If Base is correct with a proper virtual Base destructor (and not Test
destructor which is invalid) I believe this is well formed code.
Well formed -- maybe. But the code has undefined behavior as per [5.3.5/3]:

... In the second alternative (delete array) if the dynamic type of the
object to be deleted differs from its static type, the behavior is
undefined.
Best

Kai-Uwe Bux
Jun 27 '08 #4
On Apr 29, 4:32 am, "subramanian10. ..@yahoo.com, India"
<subramanian10. ..@yahoo.comwro te:
Suppose
class Base
{
public:
virtual ~Test() { ... }
// ...
};
class Derived : public Base
{
public:
virtual ~Derived() { ... }
// ...
};
int main()
{
Base* base_ptr = new Derived[10]();
delete [] base_ptr;
return EXIT_SUCCESS;
}
If the Base class dtor is not not virtual, 'delete []
base_ptr' has undefined behaviour.
Will 'delete [] base_ptr' call each Derived class dtor because
the Base::~Base() is virtual ? Is the deletion in the above
code valid ?. Or does this also invoke undefined behaviour ?
As Kai-Uwe has pointed out, it is undefined behavior. More
generally, although the compiler will tranquilly convert
Derived* to Base* even if Derived* points to an array (because
it cannot know this), the resulting pointer can only be used as
a pointer to the first individual object. In you case, for
example, no only is the delete[] undefined behavior, but any use
of base_ptr to access the allocated array (e.g. base_ptr[1])
would be as well.

In general, don't use array new; prefer std::vector. And don't
try to make array elements polymorphic; it doesn't work. (Array
elements are values, and polymorphism only works through
pointers or references. If you need an array of polymorphic
types, you must use std::vector< Base* >, allocating and
deallocating each one manually.)
--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #5
James Kanze wrote:
On Apr 29, 4:32 am, "subramanian10. ..@yahoo.com, India"
<subramanian10. ..@yahoo.comwro te:
>Suppose
>class Base
{
public:
virtual ~Test() { ... }
// ...
};
>class Derived : public Base
{
public:
virtual ~Derived() { ... }
// ...
};
>int main()
{
Base* base_ptr = new Derived[10]();
delete [] base_ptr;
return EXIT_SUCCESS;
}
>If the Base class dtor is not not virtual, 'delete []
base_ptr' has undefined behaviour.
>Will 'delete [] base_ptr' call each Derived class dtor because
the Base::~Base() is virtual ? Is the deletion in the above
code valid ?. Or does this also invoke undefined behaviour ?

As Kai-Uwe has pointed out, it is undefined behavior. More
generally, although the compiler will tranquilly convert
Derived* to Base* even if Derived* points to an array (because
it cannot know this), the resulting pointer can only be used as
a pointer to the first individual object. In you case, for
example, no only is the delete[] undefined behavior, but any use
of base_ptr to access the allocated array (e.g. base_ptr[1])
would be as well.

In general, don't use array new; prefer std::vector. And don't
try to make array elements polymorphic; it doesn't work. (Array
elements are values, and polymorphism only works through
pointers or references. If you need an array of polymorphic
types, you must use std::vector< Base* >, allocating and
deallocating each one manually.)
I understand what you are saying, but I don't understand why. Why should a
pointer from a std::vector<Bas e*be treated any different than a pointer
from Base*[] ? You state that array elements are values, but aren't the
members of containers values also? And don't most implementations of
std::vector hold their data in arrays?

It seems totally... non-intuitive and wrong to me. Can you perhaps point to
where in the standard this is stated? This is something I'm going to have
to get my head around, and right now it's just not doing it.

Thanks.

--
Jim Langston
ta*******@rocke tmail.com
Jun 27 '08 #6
Jim Langston wrote:
James Kanze wrote:
>On Apr 29, 4:32 am, "subramanian10. ..@yahoo.com, India"
<subramanian10 ...@yahoo.comwr ote:
>>Suppose
>>class Base
{
public:
virtual ~Test() { ... }
// ...
};
>>class Derived : public Base
{
public:
virtual ~Derived() { ... }
// ...
};
>>int main()
{
Base* base_ptr = new Derived[10]();
delete [] base_ptr;
return EXIT_SUCCESS;
}
>>If the Base class dtor is not not virtual, 'delete []
base_ptr' has undefined behaviour.
>>Will 'delete [] base_ptr' call each Derived class dtor because
the Base::~Base() is virtual ? Is the deletion in the above
code valid ?. Or does this also invoke undefined behaviour ?

As Kai-Uwe has pointed out, it is undefined behavior. More
generally, although the compiler will tranquilly convert
Derived* to Base* even if Derived* points to an array (because
it cannot know this), the resulting pointer can only be used as
a pointer to the first individual object. In you case, for
example, no only is the delete[] undefined behavior, but any use
of base_ptr to access the allocated array (e.g. base_ptr[1])
would be as well.

In general, don't use array new; prefer std::vector. And don't
try to make array elements polymorphic; it doesn't work. (Array
elements are values, and polymorphism only works through
pointers or references. If you need an array of polymorphic
types, you must use std::vector< Base* >, allocating and
deallocating each one manually.)

I understand what you are saying, but I don't understand why. Why
should a pointer from a std::vector<Bas e*be treated any different
than a pointer from Base*[] ? You state that array elements are
values, but aren't the members of containers values also? And don't
most implementations of std::vector hold their data in arrays?

It seems totally... non-intuitive and wrong to me. Can you perhaps
point to where in the standard this is stated? This is something I'm
going to have to get my head around, and right now it's just not
doing it.
I found it. 5.3.5.3

Quote: In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the
static type shall be a base class of the operand's dynamic type and the
static type shall have a virtual
destructor or the behavior is undefined. In the second alternative (delete
array) if the dynamic type of the
object to be deleted differs from its static type, the behavior is
undefined.

--
Jim Langston
ta*******@rocke tmail.com
Jun 27 '08 #7
* Kai-Uwe Bux <jkherci...@gmx .netwrote:
subramanian10.. .@yahoo.com wrote:
Well formed -- maybe. But the code has undefined behavior as per [5.3.5/3]:

... In the second alternative (delete array) if the dynamic type of the
object to be deleted differs from its static type, the behavior is
undefined.
I do not know about static and dynamic type.
Please give me an example so that I can understand them.

Thanks
V.Subramanian
Jun 27 '08 #8
su************* *@yahoo.com, India wrote:
* Kai-Uwe Bux <jkherci...@gmx .netwrote:
>>subramanian10 ...@yahoo.com wrote:
>Well formed -- maybe. But the code has undefined behavior as per [5.3.5/3]:

... In the second alternative (delete array) if the dynamic type of the
object to be deleted differs from its static type, the behavior is
undefined.

I do not know about static and dynamic type.
Please give me an example so that I can understand them.
class Base
{
public:
virtual ~Base() {}
};

class Derived : public Base
{};

int main()
{
Base* p = new Derived(); // static type of p is "pointer to Base"
// dynamic type of p is "pointer to Derived"
}

Jun 27 '08 #9
This is actually a response to the post you're responding to,
but since I cannot see it...

Jim Langston wrote:
Jim Langston wrote:
James Kanze wrote:
On Apr 29, 4:32 am, "subramanian10. ..@yahoo.com, India"
<subramanian10. ..@yahoo.comwro te:
Suppose
In general, don't use array new; prefer std::vector. And don't
try to make array elements polymorphic; it doesn't work. (Array
elements are values, and polymorphism only works through
pointers or references. If you need an array of polymorphic
types, you must use std::vector< Base* >, allocating and
deallocating each one manually.)
I understand what you are saying, but I don't understand why. Why
should a pointer from a std::vector<Bas e*be treated any different
than a pointer from Base*[] ? You state that array elements are
values, but aren't the members of containers values also? And don't
most implementations of std::vector hold their data in arrays?
Think about how you index into an array. And what pointer
arithmetic (which is how indexing is implemented) would mean if
you had to take into account the dynamic size. How would you
find p[1] without knowing the size of p[0]? And in the case of
p[2], what should be multiplied by 2, if p[0] and p[1] have
different sizes.

The problem here in C++ (which it inherits from C) is that even
at the user level, it makes the pointer arithmetic evident, and
doesn't distinguish between pointers to a single object, and
pointers to the first element in an array. Some of the things
you can do with a pointer (i.e. convert from Derived* to Base*)
only make sense for single objects, and other (anything
involving pointer arithmetic) only makes sense if the pointer is
in fact the address of an array.
It seems totally... non-intuitive and wrong to me. Can you perhaps
point to where in the standard this is stated? This is something I'm
going to have to get my head around, and right now it's just not
doing it.
I found it. 5.3.5.3
Quote: In the first alternative (delete object), if the static
type of the operand is different from its dynamic type, the
static type shall be a base class of the operand's dynamic
type and the static type shall have a virtual destructor or
the behavior is undefined. In the second alternative (delete
array) if the dynamic type of the object to be deleted differs
from its static type, the behavior is undefined.
That covers the delete. Something like:

struct Base
{
virtual ~Base() {}
int i ; // Take up some room.
virtual void function() ;
}

struct Derived : Base
{
int j ; // Ensure that Derived is bigger than
// Base.
virtual void function() ;
} ;

Base* p = new Derived[ 20 ] ;
++ p ;
p->function() ;

is also illegal. It can't work; there's no way to implement it
so that it does work (within the usual C++ memory model). But
finding why in the standard... It's very, very indirect, but I
suppose that the definition of pointer addition (++ is defined
in terms of addition) would cover it: "When an expression that
has integral type is added to or subtracted from a pointer, the
result has the type of the pointer operand. If the pointer
operand points to an element of an array object,[...]" In this
case, the pointer points to a Base subobject, and that Base
subobject is NOT an element of an array object. (The elements
of the array object are all Derived.) I'd prefer something more
explicit, but I think that the intent is clear.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #10

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

Similar topics

2
5407
by: Ian McBride | last post by:
(was: delete() confusion) I have a class with multiple base classes. One of these base classes (base1) has its own new/delete operators and nothing else. Another base class (base 2) has a virtual destructor. The class with the virtual destructor has AddRef() and Release() methods, and Release() ultimately does a "delete this". Can that "delete this" statement somehow find the right delete method? If it does, it involves a downcast...
9
4804
by: justanotherguy63 | last post by:
Hi, I am designing an application where to preserve the hierachy and for code substitability, I need to pass an array of derived class object in place of an array of base class object. Since I am using vector class(STL), the compiler does not allow me to do this. I do realize there is a pitfall in this approach(size of arrays not matching etc), but I wonder how to get around this problem. I have a class hierachy with abstract base...
1
16241
by: ypjofficial | last post by:
Dear All, According to OOPs , a base class pointer can to point to derived class object....call this as fact1 But somehow I am not comfortable while understanding this concept. The explanaition to the fact1 is given as since the derived object always consists of the base part , the base class pointer will always point to the base part in the derived object unless otherwise the function in the base class are declared as virtual and are...
10
3332
by: Bhan | last post by:
Using Ptr of derived class to point to base class and viceversa class base { .... } class derived : public base { .... }
5
1961
by: Michael | last post by:
Hi, Could you tell me whether the following two statement are the same? Derived class is derived from Base class. 1. Base* ptr1; 2. Derived * ptr2; Does it mean ptr1 is the same as ptr2?
3
1648
by: Nindi | last post by:
On comp.lang.c++.moderated http://groups.google.co.uk/group/comp.lang.c++.moderated/browse_thread/thread/8250715711da7760?hl=en the following question was posted ------------------------------------------------------------------------------------------------------- Is this standard conformant to type cast ::opearator delete to a function of type (void (*)(void*)); Is not operator delete already a function of this type?
1
1632
by: Gonçalo Rodrigues | last post by:
Hi all, I am a little confused about the delete operator, so I have a question. Suppose we have something like class Base { public: void* operator new(std::size_t size); void operator delete(void* ptr);
3
1620
by: Filimon Roukoutakis | last post by:
Dear all, assuming that through a mechanism, for example reflexion, the Derived** is known explicitly. Would it be legal (and "moral") to do this conversion by a cast (probably reinterpret would work here)? The conversion is done for this purpose: I have an std::map<std::string, Base*>. I want to "associate" Derived* handles to the stored Base* so when Base* in the map changes (ie points another address), the Derived* handle outside of...
10
3600
by: Dom Jackson | last post by:
I have a program which crashes when: 1 - I use static_cast to turn a base type pointer into a pointer to a derived type 2 - I use this new pointer to call a function in an object of the derived type 3 - this function then 'grows' the derived type object (by pushing onto a vector).
0
9404
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10008
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9959
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9837
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7381
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6651
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5423
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3532
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2806
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.