In Bjarne Stroustrup's "The C++ Programming Language (4th edition)" in section 17.6 (Generating Default Operations) it mentions this:
If the programmer declares a copy operation, a move operation, or a destructor for a class, no copy operation, move operation, or destructor is generated for that class.
Thus, I'm confused why the SubObj
destructor is called in this program:
#include <iostream>
using namespace std;
class SubObj {
public:
~SubObj() {
cout << "SubObj Destructor called" << endl;
}
};
class Obj {
private:
SubObj so;
public:
Obj() {};
Obj(const Obj& o) {};
};
int main() {
Obj();
cout << "Program end" << endl;
}
When compiling with g++ I get the following output:
$ ./a.out
SubObj Destructor called
Program end
Based on my understanding, I expected the default destructor for Obj
to not be auto-generated because I defined a copy operation for Obj
. And thus, I expected that the SubObj
member of Obj
would not be destroyed because there is no destructor for Obj
.
Thus, I'm wondering: are object members automatically destroyed even without a destructor? Or is a destructor somehow being auto-generated for this example?
Edit:
Later in the book (17.6.3.4), when referring to an example, Bjarne mentions:
We defined copy assignment, so we must also define the destructor. That destructor can be
=default
because all it needs to do is to ensure that the memberpos
is destyored, which is what would have been done anyway had the copy assignment not been defined.
Based on the answers so far, it sounds appears as though Bjarne may have just been wrong on this one.
No, there isn't. A static destructor supposedly would run at the end of execution of a process. When a process dies, all memory/handles associated with it will get released by the operating system.
Correct Answer : A destructor has no return type.
A non-static member function is a function that is declared in a member specification of a class without a static or friend specifier. (
It is automatically called when an object is destroyed, either because its scope of existence has finished (for example, if it was defined as a local object within a function and the function ends) or because it is an object dynamically assigned and it is released using the operator delete.
That phrase from the book is poorly worded/wrong.
Of course a destructor is still generated if you provide a copy constructor. If it weren't, your program would not be able to be compiled.
If you provide your own destructor, a destructor is not generated. It doesn't need to be, and you can't have two.
Also, members are destroyed regardless of what your destructor does. A destructor allows you to do "extra" stuff, on top of the normal rules for object (and subobject) lifetime. There was never a risk that the SubObj
member wouldn't be destroyed.
Bjarne's wording could have been better here. What
If the programmer declares a copy operation, a move operation, or a destructor for a class, no copy operation, move operation, or destructor is generated for that class.
Could more accurately be (but is still wrong, see the link below for the full rules)
If the programmer declares a copy operation, a move operation, or a destructor for a class, no copy operation, move operation, or destructor (respectively) is generated for that class.
meaning if you declare any of those special member functions, the compiler will not add it's own version. If you declare a copy constructor, it does not stop the destructor, only the copy constructor (and move in C++11+). Only defining a destructors stops the compiler from generating one. To see all of the rules see: What are all the member-functions created by compiler for a class? Does that happen all the time?
I do not have this book to check what is actually written here, but either you are quoting it incorrectly, or it is inaccurate (the latter is hard to believe). The other option is that it is just poorly phrased and confusing.
The only time when compiler will not generate an implicit destructor is when it is explicit:
If no user-declared destructor is provided for a class type (struct, class, or union), the compiler will always declare a destructor as an inline public member of its class.
https://en.cppreference.com/w/cpp/language/destructor
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With