3

Reference here

That destructor will also implicitly call the destructor of the auto_ptr object. And that will delete the pointer it holds, that points to the C object - without knowing the definition of C! That appeared in the .cpp file where struct A's constructor is defined.

This was curious and then

5.3.5/5 states - "If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined."

My question is that why isn't such a program which attempts to delete a pointer to an incomplete type treated as ill-formed? Why is it pushed into the realm of conditional (and the complete class has a non-trivial destructor..) 'undefined behavior'?

What does the 'and' imply?

EDIT 2:

Is the code below well-formed? VS and Gcc/CLang compile, but Comeau gives a warning. I guess all this is part of the undefined behavior mentioned in the Standard. My question is 'why is this not ill-formed but is undefined'?

#include <iostream>
#include <memory>
using namespace std;

struct C;
                        // Is this the POI for auto_ptr<C>? $14.6.4.1/3
struct A{
    A();
    auto_ptr<C> mc;
    ~A(){}             // how does it link to C::~C at this point?
};

struct C{};

A::A():mc(new C){}

int main(){
    A a;
}
Community
  • 1
  • 1
Chubsdad
  • 24,777
  • 4
  • 73
  • 129

1 Answers1

5

As I'm writing this your text says "Reference [here][1]" with no reference.

But essentially, the standard allows you to delete a pointer to incomplete type so that you can leverage knowledge that the compiler doesn't have, namely that the type's destructor does nothing.

std::auto_ptr is an example where this is a problem, especially for the PIMPL idiom (an infamous example of getting it wrong was Herb Sutter's GOTW on PIMPL, where he incorrectly used std::auto_ptr). boost::shared_ptr is an example where it isn't a problem (in general). That's because the constructor of boost::shared_ptr stores a deleter function, and the complete type of the pointee must necessarily be known at the point of construction.

Cheers & hth.,

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Yes. It was my overlook. Updated it – Chubsdad Oct 18 '10 at 06:10
  • +1, interesting. Does this ever actually happen, that it's necessary to delete a POD type without having its definition? Aren't classes with trivial destructors the least likely to be left incomplete? Hmfph. – Potatoswatter Oct 18 '10 at 06:27
  • can you please provide a reference to the article/material that you mentioned on gotw? – Chubsdad Oct 18 '10 at 07:37
  • 1
    @Chubsdad: OK, I did the googling for you :-), and I think [GOTW 59](http://www.gotw.ca/gotw/059.htm), fourth sub-problem, is the one. Critical for understanding that (not evident from the code presented): the impl class has to go into implementation file. Please understand that I was only referring things I know, but to find references I have to google like anyone else (it would be nice with a hotographic memory, but alas). Regarding `shared_ptr`, however, I suspect that all you have to do is to type "boost shared_ptr" in your browser's address bar, at least in Firefox. Cheers & hth., – Cheers and hth. - Alf Oct 18 '10 at 08:46
  • @Chubsdad: additional info: even as it's presented now it's still formally Undefined Behavior, but with the constructor and destructor of the public class defined in the implementation file it will in practice work with most and probably all compilers. The earliest version I can find, from 2001, still had a forward reference to GOTW 62, so I don't think the original is archived. – Cheers and hth. - Alf Oct 18 '10 at 09:03