Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Code to investigate basics of destructor

33 views
Skip to first unread message

Paul

unread,
Jan 19, 2019, 6:45:57 AM1/19/19
to
I compiled and ran the following:
Note that the whole purpose is to learn about
how the destructor works. I'm not saying that
explicitly calling the destructor here is good practice.

I have two questions.
1) Why do I need this-> for an explicit destructor call?
~Test() gives a compiler error on the grounds of no match for
operator ~ I don't understand why we need an explicit this here.

2) The output is "yes x = 0 yes". Why does the call to print() work
after the destructor has been called to destroy the object?

Thank you,

Paul

#include<iostream>
using namespace std;

class Test
{
private:
int x;
public:
~Test() { cout << " yes ";}
Test() {x = 0;}
void destroy() {this->~Test(); }
void print() { cout << "x = " << x; }
};

int main()
{
Test obj;
obj.destroy();
obj.print();
return 0;
}

Barry Schwarz

unread,
Jan 19, 2019, 8:13:11 AM1/19/19
to
On Sat, 19 Jan 2019 03:45:46 -0800 (PST), Paul <peps...@gmail.com>
wrote:
This statement causes undefined behavior since obj no longer exists
(in the way the standard describes the lifetime of an object).
However, the memory it occupied still exists physically in the
machine. You had the misfortune of being able to access that memory
and it had not yet been overwritten or reused for some other purpose.

The worst form of undefined behavior is to do "something reasonable"
or "what you expect".
> return 0;
>}

--
Remove del for email

Manfred

unread,
Jan 19, 2019, 1:10:21 PM1/19/19
to
There is a second consideration here: even if you remove the "print()"
call, still the destructor gets called twice, which is obviously wrong,
like e.g. in the following:

#include <iostream>

class X
{
public:
X() { }
~X() { std::cout << "~X();" << std::endl; }
};

int main()
{
X x;
x.~X();
}

I believe this is forbidden by the standard, but more practically it
just confirms that destructor semantics is meant to be handled by the
language itself. It is allowed to be called by the programmer only to
allow for those cases where object deallocation is not automatically
paired by object destruction, like e.g. in some vector implementation,
and in those cases it is meant as a companion to placement new.

Mr Flibble

unread,
Jan 19, 2019, 1:20:05 PM1/19/19
to
The following is legal however:

int main()
{
X x;
x.~X();
new(&x) X{};
}

/Flibble

--
“You won’t burn in hell. But be nice anyway.” – Ricky Gervais

“I see Atheists are fighting and killing each other again, over who
doesn’t believe in any God the most. Oh, no..wait.. that never happens.” –
Ricky Gervais

"Suppose it's all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That's what I would say."

Richard Damon

unread,
Jan 19, 2019, 10:14:52 PM1/19/19
to
The reason for the double destructor call is that when an blocked scope
object goes out of scope, its destructor WILL be called, the compiler
doesn't need to be smart enough to see if it has been manually called.

The normal use of explicitly calling the destructor for an object is
that the programmer is also handling the life of the storage the object
is in (and thus the object was typically created with placement new.

Another possible case is to destroy an object in place, and the rebuild
it (again with placement new).

One reason for needing the this-> on the destructor call is that your
destroy function is a very unusual case, and my technically be invoking
undefined behavior (since after you call the destructor, you are in a
member function for a now non-existent object.)

Paavo Helde

unread,
Jan 20, 2019, 4:02:28 AM1/20/19
to
On 19.01.2019 13:45, Paul wrote:
> I compiled and ran the following:
> Note that the whole purpose is to learn about
> how the destructor works. I'm not saying that
> explicitly calling the destructor here is good practice.
>
> I have two questions.
> 1) Why do I need this-> for an explicit destructor call?
> ~Test() gives a compiler error on the grounds of no match for
> operator ~ I don't understand why we need an explicit this here.

Because ~Test() means something else by grammar rules. Here is an
example (continuing the style of printing out meaningless gibberish):

#include<iostream>
using namespace std;

class Test {
private:
int x;
public:
~Test() { cout << " yes"; }
Test() { cout << " no "; x = 0; }
void destroy() { ~Test(); }
void print() { cout << " x = " << x; }
void operator~() { cout << " maybe"; }
};

int main()
{
Test obj;
obj.destroy();
obj.print();
return 0;
}

OUTPUT:
no no maybe yes x = 0 yes

Queequeg

unread,
Jan 20, 2019, 4:11:46 PM1/20/19
to
Paul <peps...@gmail.com> wrote:

> 2) The output is "yes x = 0 yes". Why does the call to print() work
> after the destructor has been called to destroy the object?

The method call works, because methods are not destroyed when the object
is destroyed. Only the data is. I don't know what the standard says about
it, but I've seen this behavior many times.

Access to `x` within print() works, because you're fortunate and nothing
overwritten this memory yet. It's not guaranteed to work.

--
https://www.youtube.com/watch?v=9lSzL1DqQn0
0 new messages