Here's a code from Stroustrup's "The C++ Programming Language" that implements a finally
which I cannot quiet understand where the destructor gets called.
template<typename F> struct Final_action
{
Final_action(F f): clean{f} {}
~Final_action() { clean(); }
F clean;
}
template<class F>
Final_action<F> finally(F f)
{
return Final_action<F>(f);
}
void test(){
int* p=new int{7};
auto act1 = finally( [&]{delete p;cout<<"Goodbye,cruel world\n";} );
}
I have two questions around this:
According to the author, the delete p
only gets called once: when act1 goes out of scope. But from my understanding: first, act1
will be initialized with the copy constructor, then the temporary object Final_action<F>(f)
in the function finally
gets destructed, calling delete p
for the first time, then a second time at the end of the function test
when act1
is out of scope. Where am I getting it wrong?
Why is the finally
function needed? Can't I just define Final_action act1([&]{delete p;cout<<"Goodbye,cruel world\n"})
? Is that the same?
Also, if anyone can think of a better title, please modify the current one.
UPDATE: After some further thinking, I'm now convinced that the destructor may be called thrice. The additional one is for the temporary objected auto-generated in the calling function void test()
used as the argument to the copy constructor of act1
. This can be verified with -fno-elide-constructors
option in g++. For those who have the same question as me, see Copy elision as well as Return value optimization as pointed out in the answer by Bill Lynch.
You are correct, this code is broken. It only works correctly when return value optimizations are applied. This line:
auto act1 = finally([&]{delete p;cout<<"Goodbye,cruel world\n"})
May or may not invoke the copy constructor. If it does, then you will have two objects of type Final_action
and you will thus call that lambda twice.
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