Pseudo-destructor call does not destroy an object
Asked Answered
S

1

17

Consider the following code:

#include <iostream>

typedef int t;
t a=42;

int main()
{
    a.t::~t();
    std::cout << a; //42
}

I'm expected that a will be destroyed. But it is not true, why? How does do that pseudo-destructor call will be destroyed the object?

Sedate answered 2/6, 2014 at 18:9 Comment(4)
What would you expect if it had been "destroyed"? Accessing an object after its lifetime has ended has undefined behaviour.Liger
Please define "destroyed". What did you expect to happen/not happen?Forewoman
@Liger I expected that there is no object denoted by a. But a still denote an object of type int with the value equals 42Sedate
@DmitryFucintv: Well... if it had been destructed, the code would have undefined behaviour. The standard imposes no requirements on code containing undefined behaviour, so a still denoting an int with value 42 would be one possible interpretation of the code (if the code did in-fact cause the lifetime of a to end).Liger
E
31

But it is not true, why?

§5.2.4/1:

The only effect is the evaluation of the postfix-expression before the dot or arrow.

Where the postfix-expression is the expression of the object for which the call takes place. Thus a pseudo destructor call, as a call to a trivial destructor, does not end the lifetime of the object it is applied to. For instance,

int i = 0;
(i += 5).~decltype(i)();
std::cout << i;

You can't actually call a destructor for scalars, because they don't have one (see [class.dtor]). The statement is solely allowed for template code in which you call the destructor of an object whose type you don't know - it removes the necessity of writing a specialization for scalar types.


It was noted in the comments that [expr.pseudo] does imply the existence of a destructor for scalars by

The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class type named by type-name.

However, this is inconsistent with other parts of the standard, e.g. §12, which calls a destructor a special member function and mentions that

A destructor is used to destroy objects of its class type.

It appears to be an imprecision created in C++98 days.

Equiprobable answered 2/6, 2014 at 18:11 Comment(11)
+1 This is the correct answer. It would be improved by expanded standard references (the part that you have quoted is not quite sufficient to completely understand the behaviour).Liger
Where is it specified that scalar type has no destructor? Can you get a reference to standard?Sedate
Caution, your code example does not compile. request for member ‘decltype’ in non-class type ‘int’. g++ -c test.cpp -std=c++11 didn't give a result too.Sedate
@DmitryFucintv: Works-for-me... looks like a gcc bug.Liger
@DmitryFucintv Added the explanation. And the code example compiles well under Clang, GCC simply has a bug here.Equiprobable
Could you say whether std::cout << a; causes undefined behaviour?Rothermere
The standard says "The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class type denoted by type-name or decltype-specifier." This suggests that the type does have a destructor. (If it did not have a destructor then its destructor could not be represented). However 12.4 seems to say there are no destructors for non-class types. Perhaps the text "represents the destructor" is just sloppy wording.Rothermere
@Matt Accessing a is fine as a's lifetime does not end as specified by 3.8. The wording could be sloppy, yeah. I'll potentially extend the answer once I'm back and have a laptop.Equiprobable
@Columbo: what is difference between pseudo destructor & trivial destructor? Are both same? It would be better if you will give an program in which you call the destructor of an object whose type isn't known- & how it removes the necessity of writing a specialization for scalar (or even array) types. ?Glowing
@PravasiMeet There is no such thing as a "pseudo destructor", and a pseudo destructor call calls nothing at all - the call is pseudo, not the destructor. A trivial destructor is simply a destructor that performs no action at all (i.e., a no-op).Equiprobable
Note that C++20 changed this point and made this expression valid (see 7.5.4.4 Destruction)Backstop

© 2022 - 2024 — McMap. All rights reserved.