Topic: Call Destructor" Vs. "Destruct Object
Author: "jose.diego@gmail.com" <jose.diego@gmail.com>
Date: Wed, 27 Sep 2006 14:46:54 CST Raw View
Frederick Gotham wrote:
> Alberto Ganesh Barbati posted:
>
> > Again you are separating the *body* of the destructor from the
> > destructors of the class subobject. There is no such separation.
>
>
> If there's no such separation, then why does the invocation of a destructor
> have the exact same syntax by which we invoke a member function?
>
> --
>
> Frederick Gotham
I can't get your point. Since you are invoking the destructor manually
due to placement new, why should this invocation have a different
syntax from a member function?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Wed, 27 Sep 2006 14:46:19 CST Raw View
Frederick Gotham wrote:
> Alberto Ganesh Barbati posted:
>
> > Again you are separating the *body* of the destructor from the
> > destructors of the class subobject. There is no such separation.
>
>
> If there's no such separation, then why does the invocation of a destructor
> have the exact same syntax by which we invoke a member function?
I'm afraid that I don't follow the connection you're making between the
syntax and the semantics.
Regardless of the similarity in syntax, the defined semantics for the
destructor are different from the semantics defined for most other
member functions, in many different ways. In particular, the defined
semantics include automatic invocation of the destructors for
non-static data members of class type after completion of the body of
the containing object's destructor. The only other class members with
comparable semantics are constructors, which are defined as invoking
the constructors of non-static data members of class type before
entering the body of the containing object's constructor.
You wrote:
> char *const mem = new char[sizeof(MyStruct)]; /* Allocate the memory */
>
> MyStruct *const p = ::new(mem) MyStruct(5); /* Construct the object */
>
> p->~MyStruct(); /* Destruct the object */
>
> delete [] mem; /* Deallocate the memory */
>
> Notice that when we are destructing the object, it looks as though we're
> simply invoking the MyStruct destructor -- but in actuality, we're really
> doing:
>
> p->member.~string();
> p->~MyStruct();
>
> This is inconsistent with the way in which we construct the object!
There's an inherent inconsistency because the constructor can't be
called with member function syntax, because the object it would be
called upon doesn't exist yet, whereas the object to be destroyed, by
definition, does exist. However, I presume that's not the inconsistency
you're talking about.
I'm not sure what inconsistency you're seeing with the way the object
is constructed. The constructor calls the constructors of the the
subobjects, in exact mirror symmetry to way the destructor calls the
destructors for those same subobjects. It's a mirror symmetry, because
the order is exactly reversed, as it should be. That strikes me as very
consistent, and essential to idea that construction and destruction
occur, for the most part, automatically, without the C++ programmer
having to go out of his way to arrange it. As I understand your
proposal, I'd have to add to every one of my destructors explicit calls
to the destructors of every member that the destructor currently
automatically calls for me.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 27 Sep 2006 20:12:12 GMT Raw View
jose.diego@gmail.com posted:
> I can't get your point. Since you are invoking the destructor manually
> due to placement new, why should this invocation have a different
> syntax from a member function?
Let's say that the destructor of our class is defined as follows:
MyClass::~MyClass()
{
delete [] p; /* "p" is a member object */
}
If we were to invoke this function just like any other member function, then
all it would do is execute the "delete [] p;". However, more things happen,
specifically the calling of the destructors of any base object and
subobjects.
It looks like an ordinary member function call, but it does more.
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 27 Sep 2006 20:13:45 GMT Raw View
kuyper posted:
> As I understand your proposal, I'd have to add to every one of my
> destructors explicit calls to the destructors of every member that the
> destructor currently automatically calls for me.
No, that's not what I'm saying. I'll try to explain. A destructor looks
like any other member function, e.g.:
MyClass::~MyClass()
{
delete [] p;
}
Furthermore, it can be invoked just like any other member function:
obj.~MyClass();
-- however, calling the destructor does more than simply execute the
function, it also calls the destructors of any base objects or subobjects.
The die is cast now, so there's no point in changing "obj.~MyClass();" to
result in a call to the sole destructor and nothing more. What would have
been nice is if "placement delete" were used to destruct an object, and
then explicit destructor calls could simply be forbidden, i.e.:
obj.~MyClass(); /* Compile ERROR */
Or, an other option would have been for the calling of the destructor to
result in the sole invocation of that destructor and none others -- sure it
doesn't make sense, but I'm sure someone would find a use for it somewhere.
Anyway, C and C++ have always been about giving the programmer supreme
control.
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: jdennett@acm.org (James Dennett)
Date: Wed, 27 Sep 2006 20:59:37 GMT Raw View
Frederick Gotham wrote:
> Alberto Ganesh Barbati posted:
>
>> Again you are separating the *body* of the destructor from the
>> destructors of the class subobject. There is no such separation.
>
>
> If there's no such separation, then why does the invocation of a destructor
> have the exact same syntax by which we invoke a member function?
That seems somewhat non-sequiteur. Invocation of a
destructor has special syntax in the C++ grammar;
it's discussed in [expr.pseudo], "Pseudo destructor
call".
The destructor destroys the whole object. This means
that it runs user-supplied code from the body of the
destructor, and then runs relevant destructors for
subobjects, just as a constructor runs constructors
for subobjects before running the code from its body.
It's convenient to use foo.~Foo() or foo->~Foo() as
notationf or this; why not? It's similar to notation
for a member function call, which is nice, but different
enough not to be confused with a call to a regular
member function.
-- James
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Edward Rosten" <Edward.Rosten@gmail.com>
Date: Wed, 27 Sep 2006 16:33:34 CST Raw View
Frederick Gotham wrote:
> If we have a simple class such as follows:
>
> #include <string>
>
> struct MyStruct {
>
> std::string member;
>
> MyStruct(unsigned const i)
> {
> member += '0'+i;
> }
> };
>
[snip]
> The DIY invocation of a destructor via "obj.~Class();" should either:
.
> (2) Just call _that_ destructor, exactly as if it were a member
> function, without invoking any other destructors (such as those of base
> objects or subobjects.
Why do you want that? If string isn't destructed when MyStruct is, then
any memory used by string on the heap will loose any references to it,
but not be freed, causing a memory leak.
Can you give an example of when you would ever want to `partially'
destruct an object in the way you suggest (ie not destructing its
members/parents)?
-Ed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: kuyper@wizard.net
Date: Wed, 27 Sep 2006 16:46:03 CST Raw View
Frederick Gotham wrote:
> kuyper posted:
>
> > As I understand your proposal, I'd have to add to every one of my
> > destructors explicit calls to the destructors of every member that the
> > destructor currently automatically calls for me.
>
>
> No, that's not what I'm saying. I'll try to explain. A destructor looks
> like any other member function, e.g.:
>
> MyClass::~MyClass()
> {
> delete [] p;
> }
>
> Furthermore, it can be invoked just like any other member function:
>
> obj.~MyClass();
>
> -- however, calling the destructor does more than simply execute the
> function, it also calls the destructors of any base objects or subobjects.
> The die is cast now, so there's no point in changing "obj.~MyClass();" to
> result in a call to the sole destructor and nothing more. What would have
> been nice is if "placement delete" were used to destruct an object, and
> then explicit destructor calls could simply be forbidden, i.e.:
>
> obj.~MyClass(); /* Compile ERROR */
I never even gave any serious thought to that option. It would break
too much existing code, including in particular most (probably all)
implementations of standard-conforming allocator classes.
> Or, an other option would have been for the calling of the destructor to
> result in the sole invocation of that destructor and none others -- sure it
> doesn't make sense, but I'm sure someone would find a use for it somewhere.
That's the case I was thinking of. With that change, I would have to
make the changes I described in my previous message, to any of my
destructors for which there's a chance of an explicit destructor call
occurring. Please note that one of the required members of a standard
allocator has it's required behavior defined in terms of explicit calls
to the destructor (I think it's named destroy(), but I don't have my
copy of the standard readily available, so I can't confirm that). All
of the standard containers are defined as using allocators which meet
those requirements to perform their construction and destruction of the
contained objects. Therefore, it's a pretty common for a destructor to
be called explicitly, even if it doesn't occur in your own code.
> Anyway, C and C++ have always been about giving the programmer supreme
> control.
I'm sure you'll be able to come up with some reason why you want to
destroy an object without destroying it's sub-objects; but that doesn't
even come close to being the normal case. If your reason is a good one,
I'd guess that you can get the desired semantics, without a change to
the language, simply by changing your code. replacing the members that
you don't want destroyed with pointers to seperately allocated objects.
You'll have all the control that you want over when those other objects
are created and destroyed; nothing will happen to them automatically.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Wed, 27 Sep 2006 18:29:49 CST Raw View
Frederick Gotham ha scritto:
> No, that's not what I'm saying. I'll try to explain. A destructor looks
> like any other member function, e.g.:
>
> MyClass::~MyClass()
> {
> delete [] p;
> }
>
> Furthermore, it can be invoked just like any other member function:
>
> obj.~MyClass();
>
> -- however, calling the destructor does more than simply execute the
> function, it also calls the destructors of any base objects or subobjects.
You said it correctly: a destructor *looks like* a regular member
function, but it isn't. Destructors were made to *look like* member
functions just for the programmer's convenience. The syntax could have
been different, but someone (Stroustrup?) chose that one because it just
seemed right. Why do you want to take that as a precedent to justify
that destructors should behave as regular functions? If that's the only
reason, it's too weak to be even considered.
> -- however, calling the destructor does more than simply execute the
> function, it also calls the destructors of any base objects or subobjects.
> The die is cast now, so there's no point in changing "obj.~MyClass();" to
> result in a call to the sole destructor and nothing more. What would have
> been nice is if "placement delete" were used to destruct an object, and
> then explicit destructor calls could simply be forbidden, i.e.:
>
> obj.~MyClass(); /* Compile ERROR */
This idea can't be considered because it would break existing code.
> Or, an other option would have been for the calling of the destructor to
> result in the sole invocation of that destructor and none others -- sure it
> doesn't make sense, but I'm sure someone would find a use for it somewhere.
> Anyway, C and C++ have always been about giving the programmer supreme
> control.
I can't find a weaker rationale from "I'm sure someone would find a use
for it somewhere". Any proposal for a core language change should be
motivated by a real-life use case.
BTW, if a programmer needed your "bare destructor" thing, he/she can
have it *right now*, no change in the language is necessary:
struct MyClass
{
~MyClass() { destroy(); }
void destroy() { /* actual destructor code here */ }
};
Notice that if you call destroy(), the "real" destructor will still be
called, sooner or later, so you end up calling destroy() twice. This
might be a good reason for *not* wanting the feature you are proposing.
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Tue, 26 Sep 2006 20:48:34 GMT Raw View
If we have a simple class such as follows:
#include <string>
struct MyStruct {
std::string member;
MyStruct(unsigned const i)
{
member += '0'+i;
}
};
, then using "placement new" to construct an object of the class does the
following:
(1) Calls the constructor of the member object, "member".
(2) Calls the MyStruct constructor for the object itself.
This is conceivibly quite realistically like:
mystruct_obj.member.string();
mystruct_obj.MyStruct();
(i.e. we're invoking the code of two constructors.)
However, take a look at the following life-cycle of a DIY object, paying
particular attention to the way in which we destruct the object:
char *const mem = new char[sizeof(MyStruct)]; /* Allocate the memory */
MyStruct *const p = ::new(mem) MyStruct(5); /* Construct the object */
p->~MyStruct(); /* Destruct the object */
delete [] mem; /* Deallocate the memory */
Notice that when we are destructing the object, it looks as though we're
simply invoking the MyStruct destructor -- but in actuality, we're really
doing:
p->member.~string();
p->~MyStruct();
This is inconsistent with the way in which we construct the object! But not
only that, it's misleading because we are _not_ simply calling the
destructor -- we're doing more than that, we're invoking the constructors
of all base classes and subobjects. For consistency, we should have either
had:
Solution (1) -- Not favourable
char *const mem = new char[sizeof(MyStruct)];
MyStruct &obj = reinterpret_cast<MyStruct&>(*mem);
obj.MyClass(5); /* Construct! */
obj.~MyClass(); /* Destruct! */
delete [] mem;
Solution (2) -- Quite favourable
char *const mem = new char[sizeof(MyStruct)];
MyStruct *const p = ::new(mem) MyClass(5);
::delete(p) MyClass; /* Placement delete! */
The second solution is favourable, as it makes no mention of calling
constructors or destructors, but rather introduces the idea of
"constructing" and "destructing" an object (which may involve the
invocation of one or more constructors/destructors for base classes or
subobjects, etc.). The first solution is downright misleading, because it
resembles exactly the way in which we normally invoke a member function,
and gives no indication that we're also invoking the
constructors/destructors of base classes and subobjects.
My own opinion is that there should be a "placement delete", whose purpose
it is to destruct an object.
The DIY invocation of a destructor via "obj.~Class();" should either:
(1) Be forbidden, as it is for constructors.
(2) Just call _that_ destructor, exactly as if it were a member
function, without invoking any other destructors (such as those of base
objects or subobjects.
Maybe the die is cast... but it's worth a think.
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Wed, 27 Sep 2006 04:27:32 GMT Raw View
Frederick Gotham ha scritto:
> , then using "placement new" to construct an object of the class does the
> following:
>
> (1) Calls the constructor of the member object, "member".
> (2) Calls the MyStruct constructor for the object itself.
Not exactly. The placement new does this:
(1) calls the constructor of the MyStruct
It's part of the execution of MyStruct::MyStruct to construct any base
class and member objects. You can't think of the actual code block of
the constructor as something separated from the initialization of
subobjects.
> This is conceivibly quite realistically like:
>
> mystruct_obj.member.string();
> mystruct_obj.MyStruct();
>
> (i.e. we're invoking the code of two constructors.)
That's the effect, but technically speaking it's only
mystruct_obj.MyStruct();
during the execution of which mystruct_obj.member.string(); will
eventually be called.
> However, take a look at the following life-cycle of a DIY object, paying
> particular attention to the way in which we destruct the object:
>
> char *const mem = new char[sizeof(MyStruct)]; /* Allocate the memory */
>
> MyStruct *const p = ::new(mem) MyStruct(5); /* Construct the object */
>
> p->~MyStruct(); /* Destruct the object */
>
> delete [] mem; /* Deallocate the memory */
>
> Notice that when we are destructing the object, it looks as though we're
> simply invoking the MyStruct destructor -- but in actuality, we're really
> doing:
>
> p->member.~string();
> p->~MyStruct();
Again you are separating the *body* of the destructor from the
destructors of the class subobject. There is no such separation. So you
just call p->~MyStruct(), which eventually will call p->member.~string();.
> This is inconsistent with the way in which we construct the object! But not
> only that, it's misleading because we are _not_ simply calling the
> destructor -- we're doing more than that, we're invoking the constructors
> of all base classes and subobjects. For consistency, we should have either
> had:
I'm sorry but I can see no inconsistency and I can't see what are you
aim at. It's a nonsense to try to either construct or destroy an object
without constructing or destructing its subobjects.
> My own opinion is that there should be a "placement delete", whose purpose
> it is to destruct an object.
You don't need such thing. obj.~Class() is the right tool and the only
one you'll ever need.
Regards,
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Geo" <gg@remm.org>
Date: Wed, 27 Sep 2006 08:49:53 CST Raw View
Frederick Gotham wrote:
>
> Maybe the die is cast... but it's worth a think.
>
No it's not, it doesn't make any sense at all, I think you have a
fundamental misunderstanding of the concepts of construction and
destruction !
> --
>
> Frederick Gotham
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Wed, 27 Sep 2006 16:53:28 GMT Raw View
Alberto Ganesh Barbati posted:
> Again you are separating the *body* of the destructor from the
> destructors of the class subobject. There is no such separation.
If there's no such separation, then why does the invocation of a destructor
have the exact same syntax by which we invoke a member function?
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]