home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 31,483 of 33,346   
   =?ISO-8859-1?Q?Daniel_Kr=FCgler?= to Agents Marlow   
   Re: deleting an array of objects and und   
   23 Sep 11 12:05:31   
   
   522ced26   
   From: daniel.kruegler@googlemail.com   
      
   On 2011-09-23 15:09, Agents Marlow wrote:   
   > I have just come across something I didn't know from the std:   
   >   
   > When deleting an array, the dynamic and the static type of the object   
   > must be the same, or the behavior is undefined (C++ Standard 5.3.5/3).   
      
   Correct.   
      
   > I was amazed to discover this. It was revealed to me in a test   
   > question where it had a code fragment and said "what, if anything, is   
   > wrong with this code?". Here is the code:   
   >   
   > struct X {   
   >    virtual ~X() {}   
   > };   
   >   
   > class Y : public X {   
   > };   
   >   
   > int main() {   
   >    X* p = new Y[2];   
   >    delete [] p;   
   >    return 0;   
   > }   
   >   
   > The above code has undefined behaviour according to the std. But why?   
   > I really don't understand. The usual gotcha when doing polymorphic   
   > deletes is forgetting to make the dtor of the base class virtual but   
   > that has been done here and it's still undefined behaviour!   
      
   This is the root of the misunderstanding: The virtual destructor only   
   helps to make polymorphic deletes of *objects* of the corresponding type   
   well-defined, but you would need the concept of a virtual destructor for   
   array objects to make a polymorphic delete of the array well-defined.   
   But there does not exist such a concept in C++.   
      
   You can look at this the following way: array-new allocates a continuous   
   memory block for the whole number of elements (these are known   
   statically). Deleting this array via array-delete does not perform any   
   polymorphic action on the array elements, because they are statically   
   determined by the type of the array, so it does not help here that X has   
   a virtual destructor - only the statically determined destructor of the   
   element type will be invoked.   
      
   > If one wanted an array of base class pointers then how would one   
   > delete the objects when the time comes? Would it be ok to have a   
   > vector of boost::shared_ptrs?   
      
   This would work, because the std::vector will simply invoke the deleter   
   of the shared_ptr's which knows the correct deleter of it's pointee.   
   Note the difference: Here you are using an array of *pointer* to items.   
   But that was not what you used in your original example: There you used   
   an array of (non-pointer) elements.   
      
   > Or would that boil down to the above and   
   > thus yield undefined behaviour also? I am worried if the answer to   
   > that is "yes" because I have written such code recently. I hope it   
   > would be ok since the container is a vector rather than a native   
   > array.   
      
   This is OK.   
      
   > Perhaps it is native arrays that are the source of the trouble   
   > for reasons I don't understand.   
      
   The problem is one, which cannot happen with std::vector. You either   
   could form std::vector or std::vector, but both vectors have no   
   inheritance relation to each other. They are not even assignable to each   
   other. Given   
      
   std::vector x;   
   std::vector y;   
      
   neither of   
      
     y = x;   
     x = y;   
      
   would be well-formed. The problem with the native array is the implicit   
   conversion to pointer and the fact that Y* is convertible to X*. Because   
   of this danger the specialization of std::unique_ptr for arrays is   
   required to reject pointer arguments to the constructors or the reset   
   function which are convertible (and not identical) to the pointee type   
   (The template argument) of std::unique_ptr.   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca