Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

destructors: triviality vs implicit definition

Tags:

c++

destructor

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...

like image 619
abigagli Avatar asked Jan 24 '23 22:01

abigagli


2 Answers

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.

like image 69
Johannes Schaub - litb Avatar answered Feb 02 '23 02:02

Johannes Schaub - litb


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++.

like image 45
MSalters Avatar answered Feb 02 '23 02:02

MSalters