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?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
  • 10
    What would you expect if it had been "destroyed"? Accessing an object after its lifetime has ended has undefined behaviour. – Mankarse Jun 02 '14 at 18:11
  • 1
    Please define "destroyed". What did you expect to happen/not happen? –  Jun 02 '14 at 18:12
  • @Mankarse I expected that there is no object denoted by a. But a still denote an object of type int with the value equals 42 –  Jun 02 '14 at 18:14
  • 1
    @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). – Mankarse Jun 02 '14 at 18:18

1 Answers1

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.

AndyG
  • 39,700
  • 8
  • 109
  • 143
Columbo
  • 60,038
  • 8
  • 155
  • 203
  • 2
    +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). – Mankarse Jun 02 '14 at 18:15
  • Where is it specified that scalar type has no destructor? Can you get a reference to standard? –  Jun 02 '14 at 18:18
  • 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. –  Jun 02 '14 at 18:21
  • @DmitryFucintv: [Works-for-me](http://coliru.stacked-crooked.com/a/8acec373745590f8)... looks like a gcc bug. – Mankarse Jun 02 '14 at 18:22
  • 1
    @DmitryFucintv Added the explanation. And the code example compiles well under Clang, GCC simply has a **bug** here. – Columbo Jun 02 '14 at 18:24
  • Could you say whether `std::cout << a;` causes undefined behaviour? – M.M Aug 26 '15 at 03:57
  • 1
    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. – M.M Aug 26 '15 at 04:12
  • 2
    @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. – Columbo Aug 26 '15 at 08:12
  • @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. ? – Destructor Aug 26 '15 at 16:32
  • 5
    @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). – Columbo Aug 26 '15 at 17:05
  • Note that C++20 changed this point and made this expression valid (see 7.5.4.4 Destruction) – informaticienzero May 21 '21 at 17:15