Quote:Original post by Anonymous PosterQuote:Original post by Bregma
This has the advantage that you don't need to write your own destructor to delete m_x, the default destructor will do the right thing, ...
No it won't, in this case.
It won't even compile without X defined ("new X" is invalid at that point in this translation unit otherwise)
Quote:It will ONLY be deleted properly if the class has a non-default destructor.
Not true - for both MSVC++ 2k5 and GCC 3.4.2, if X is defined in the same translation unit (even if forward declared originally as above) ~X is properly called.
The issue you're thinking of occurs when:
1) You destroy the containing object (of type C) in a translation unit T
2) The containing object (of type C) uses a default destructor.
3) You never define the contained type (X) in translation unit T.
#include <memory>#include <iostream>class X;class C{private: std::auto_ptr< X > m_x;public: C(); //deffered until X defined //default destructor};int main () { C c;} //result: ~X when c goes out of scope.class X { public: ~X() { std::cout << "~X" << std::endl; } };C::C() : m_x( new X ) {}
Any compiler claiming to be modern should display a warning when invoking such behavior. Both MSVC++ 2k5 and GCC 3.4.2 do at least, with default settings.
There is an alternative scenario:
1) You destroy the containing object (of type C).
2) The containing object (of type C) uses a non-default destructor, defined in translation unit T.
3) You never define the contained type (X) in translation unit T.
MSVC++ 2k5 dosn't seem to catch this one, oddly. GCC 3.4.2 generates warnings.
// c.hpp ////////////////#include <memory>class X;class C{private: std::auto_ptr< X > m_x;public: C(); //deffered until X defined ~C();};// x.cpp ////////////////#include <iostream>#include "c.hpp"class X { public: ~X() { std::cout << "~X" << std::endl; } };C::C() : m_x( new X ) {} //here because we need X defined to new it.// c.cpp ////////////////#include "c.hpp"C::~C() {} //here because we need X not defined to show the problem// main.cpp /////////////#include "c.hpp"int main () { C c;} //result: no ~X
Both these scenarios have 1 thing in common: X's destructor is not defined in the same translation as C's, whether C's is compiler generated ("default") or explicit.