Reputation: 3164
I have this example:
struct A{
A(){std::cout << "A's def-ctor\n";}
~A(){std::cout << "A's dtor\n";}
A(A const&){std::cout << "A's copy-ctor\n";}
A& operator = (A const&){std::cout << "A's copy-assign op\n"; return *this; }
};
struct Foo{
Foo() : curMem_(INT), i_(0){}
~Foo(){
if(curMem_ == CLS_A) // If I comment out this line then what happens?
a_.~A();
}
enum {INT, CHAR, CLS_A, BOOL} curMem_;
union{
int i_;
char c_;
A a_;
bool b_;
};
};
Foo f;
f.curMem_ = Foo::CLS_A;
f.a_ = A();
f.curMem_ = Foo::BOOL;
f.b_ = true;
We know that a class default destructor doesn't know which member of a class's member of a union type is active that is why we do need to define out version of destructor. So union's member data of class type are not automatically destroyed. So What will happen if I don't explicitly call the destructor of those class type member of the union?
If I comment the line in Foo
destructor or remove the destructor itself what will happen? Is it undefined behavior?
My class A
doesn't manage a resource via a raw pointer then why I bother to explicitly call its destructor when an of object of it is a member of a union
? Thank you!
P.S: I have this from C++ primer 5th edition Chapter 19.6 unions:
Our destructor checks whether the object being destroyed holds a string. If so, the destructor explicitly calls the string destructor (§ 19.1.2, p. 824) to free the memory used by that string. The destructor has no work to do if the union holds a member of any of the built-in types.
"The destructor has no work to do if the union holds a member of any of the built-in types." I think he could add: "or of a class type which depends on the trivial destructor". What do you think?
Upvotes: 3
Views: 161
Reputation: 40801
The exact wording of the standard given in [basic.life]p6
is:
For an object of a class type, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression ([expr.delete]) is not used to release the storage, the destructor is not implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
(emphasis mine)
"depends on the side effects" seems pretty vague, and there are plenty of questions on stack overflow discussing this wording. Your A
class's destructor seems to have the side effect of calling an I/O function, so it seems like you run into undefined behaviour.
Even if it wasn't UB, if it was a std::vector
, std::string
or std::fstream
, you would leak resources like memory or file handles. It depends entirely on what the destructor of the class (and any members of that class) do.
Since "My class A
doesn't manage a resource via a raw pointer", it should really have a trivial destructor. In which case, this point is moot and it is fine to not call the destructor.
Upvotes: 4