views:

743

answers:

3

As I understand the standard, a trivial destructor is one which is implicitly declared and whose class has only base and non-static members with trivial destructors. Given the recursivity of this definition, it seems to me that the only "recursion-stopping" condition is to find a base or non-static member with a non-implicitly declared destructor (i.e. user declared). If that's right, that should mean that a trivial destructor is one which "doesn't have to do anything" and hence it will be declared (implicitly) but not defined. Saying it in another way: is it correct to say that an implicitly defined destructor (that is "it does something") cannot be trivial as per the standard definition?

Sorry for the kind of silly question, but I'd like to clarify things a bit in my head...

+3  A: 

No. An implicitly defined, trivial destructor is by definition trivial :) The difference between the declare and define thingy is that in order for the compiler to even see that a destructor is available, there must always a declaration. So if you don't provide one, it will implicitly provide one.

But now, it will also define one, if that is needed (if an object of that class type is destroyed). In any case, it has to do something: It needs to call the destructors of all its members and base classes. A simple example which illustrates the effect of implicitly defining a destructor:

struct a {
private:
    ~a();
};

struct bug {
    // note: can't be destructed
    a a_;
};

As soon as you try to create a local object of bug, the compiler will signal an error, because it yields a definition of a destructor for bug, which tries to call the not accessible destructor of a.

Now, i think triviality of destructors/constructors are mostly used to put constraints on your program. Objects having non-trivial versions of them can't be put in unions, for example. On the other side, you can delete an object having incomplete type, provided it has a trivial destructor. Note that if your program can't decide whether or not a trivial destructor was actually defined, the compiler is allowed to omit defining it. That's the so-called as-if rule. The compiler has to behave as-if it's Standard compliant - optimizations do not matter as long as they don't change the meaning of a program.

Johannes Schaub - litb
Well, my point is: if, using your words, "that is needed", it means it "has to do something", which I cannot see how could it be in case it's trivial. In other words again: can you give me an example of a trivial destructor that "does something"?
abigagli
well, we have two things: triviality and implicit. the implicit definition *can* cause side effects. then there is triviality, which is used to define restrictions on how objects can be used in certain cases (delete on a pointer to incomplete type, for example)
Johannes Schaub - litb
for example if you have a template class, and in a destructor of a base-class you reference a static member of that template class, the derived class' implicit definition of its destructor will cause the static member of the template class to be instantiated.
Johannes Schaub - litb
i did enumerate the different cases for implicitly defined constructors here: http://stackoverflow.com/questions/401621/best-way-to-build-a-list-of-per-type-data#401801
Johannes Schaub - litb
Ok, I think I'm getting to it, I just can't understand this "Note that if your program can't decide whether or not a trivial destructor was actually defined, the compiler is allowed to omit defining it.".Could you please eleborate a bit on it? Thanks.
abigagli
oh i guess it's my bad english. I mean if yor program can't see the difference between the dtor being defined or not being defined, the compiler can omit defining the dtor. rules in the standard describe the abstract semantics. what the compiler really does is up to him
Johannes Schaub - litb
i think this is appropriate: http://stackoverflow.com/questions/405770/why-are-compilers-so-stupid#406311 :)
Johannes Schaub - litb
A: 

Consider these two classes:

class A {
};

class B {
private:
     A obj;
};

The destructors of both these classes implicitly defined. Yet, at the same time, both of them are trivial by the standard definition.

Frederick
+2  A: 

Your wording is a bit unfortunate. E.g. the recursion of course also ends when you run out of members and base classes. Those wording problems also seem to get you more confused.

Anyway, all implicitly-declared destructors, whether they are trivial or not, are defined if and only if they are used. Used is a specific term here. A destructor of type T is used whenever the lifetime of a T object ends.

Trivial destructors exist because C programmers put structs in unions. This code should remian legal in C++, so the notion of a trivial destructor was invented for C++. All C structs have trivial destructors, when compiled as C++.

MSalters