Call Destructor and Then Constructor (Resetting an Object)

Call destructor and then constructor (resetting an object)

Don't get sucked in by the FQA troll. As usual he gets the facts wrong.

You can certainly call the destructor directly, for all objects whether they are created with placement new or not. Ugly is in the eye of the beholder, it is indeed rarely needed, but the only hard fact is that both memory allocation and object creation must be balanced.

"Regular" new/delete simplifies this a bit by tying memory allocation and object creation together, and stack allocation simplifies it even further by doing both for you.

However, the following is perfectly legal:

int foo() {
CBar bar;
(&bar)->~CBar();
new (&bar) CBar(42);
}

Both objects are destroyed, and the stack memory is automatically recycled too. yet unlike the FQA claims, the first call of the destructor is not preceded by placement new.

Is it ok to use the destructor inside function of a class to reset values?

Calling a non-trivial destructor explicitly ends object's lifetime (why?).

Share the functionality between ResetStats and destructor by putting it in a separate private function:

// Both destructor and ResetStats call Reset
~Test1(){
Reset(nullptr);
}
void ResetStats(int NewValue) {
Reset(new int(NewValue));
}
// Shared functionality goes here
private Reset(int *ptr) {
delete test;
test=ptr;
valid=false;
}

Reset an object

By definition, if you assign a new value to an old object, the new value has been constructed before the assignment can take place.

Your 'old object' is not really destructed, either.

So No. There is no way. And there shouldn't: you shouldn't redefine the 'obvious' behavior of the assignment operator.

But placement new could help here apart from the tilde and exotic construction syntax, maybe this code approaches 'clean' :)

Foo old(a, b, c);
old.~Foo(); // explicit destruction
new (&old) Foo(d, e, f);

Automatic destruction of object even after calling destructor explicitly

You've introduced undefined behavior.

Per the standard:

§ 12.4 Destructors

(11) A destructor is invoked implicitly

(11.3) — for a constructed object with automatic storage duration (3.7.3) when the block in which an object is
created exits
(6.7),

and

15 Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the
destructor is invoked for an object whose lifetime has ended (3.8). [ Example: if the destructor for an
automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily
invoke implicit destruction of the object, the behavior is undefined. —end example ]

You explicitly call the destructor or by calling t.~Test(), it is then implicitly invoked when the object leaves scope. This is undefined.

The standard provides this note as well:

14 [ Note: explicit calls of destructors are rarely needed. One use of such calls is for objects placed at specific
addresses using a placement new-expression. Such use of explicit placement and destruction of objects can
be necessary to cope with dedicated hardware resources and for writing memory management facilities.

Is it defined behavior to explicitly call a destructor and then use placement new to reconstruct it?

Unfortunately, sometimes it is defined behavior, and other times you have to run the pointer through std::launder. There are a number of cases where the compiler may assume that the object hasn't changed, particularly if there are references or const fields in struct S. More information is available in the cppreference section on storage reuse.

In the particular code that you show, you will run into problems if S is a base class of the complete object, because the compiler could, for example, be caching to wrong vtable somewhere.

In a bit more detail, this is something that has changed between C++17 and C++20. In C++17 and earlier, you need to call std::launder when S contains any const or reference fields. However, that particular requirement has been relaxed in C++20, though there are still other restrictions.

std::unique_ptr destructor constructor order

The reason the constructor is invoked before the destructor of the previous instance, is because you're passing new my_class() as an argument to the unique_ptr's constructor. The argument is evaluated first, constructing a new unique_ptr instance which takes ownership of the newly created object, then that new unique_ptr instance is assigned to the old.

As a result, the old unique_ptr's my_class object it had ownership of will be deallocated and destructed, invoking the my_class destructor.

It's effectively the same as if you had written:

my_class* temp = new my_class;
test = std::unque_ptr<my_class>(std::move(temp));

Here it's directly visible that the new object is constructed first.

Why not call Destructor in C++?

Why destructor not call implicit by the compiler upon exit program?

Because dynamically allocated objects are not destroyed automatically. That is how the language has been specified. Tracking the destruction of dynamic objects would require runtime / memory overhead.

Solution: Do not leak dynamically allocated objects.



Related Topics



Leave a reply



Submit