2 ms·
unique_ptr/shared_ptr don't make a difference with regard to whether or not you need to use function-try blocks. function-try blocks are about whether the excep
by nly 13y ago
unique_ptr/shared_ptr don't make a difference with regard to whether or not you need to use function-try blocks. function-try blocks are about whether the exception leaves the constructor, not whether the exception will result in destructors being called. For cleanup of constructed members when an exception is thrown in the ctor init-list it is required that you're in a try block somewhere up the stack.
Observe: https://ideone.com/DYthrB https://ideone.com/DYthrB
#include <iostream>
#include <memory>
struct Foo {
int x_;
Foo (int const x): x_(x) {
if (x == 1) {
throw x;
}
}
~Foo() { std::cerr << "foo_" << x_ << " destroyed" << std::endl; }
};
struct Bar {
std::shared_ptr<Foo> foo_0;
std::shared_ptr<Foo> foo_1;
std::shared_ptr<Foo> foo_2;
Bar():
foo_0 (std::make_shared<Foo>(0)),
foo_1 (std::make_shared<Foo>(1)),
foo_2 (std::make_shared<Foo>(2)) {
}
~Bar() {
std::cerr << "Bar destroyed" << std::endl;
}
};
void xul() {
Bar bar;
}
int main() {
try { xul(); } catch (...) { return EXIT_FAILURE; }
}
Outputs:
foo_0 destroyed
foo_0 was destroyed here even though Bars destructor was never called
Change main to:
int main() { xul(); }
Outputs nothing. foo_1 doesn't leak memory (it's freed by the shared_ptr constructor when Foos constructor throws) but foo_0 leaks because no shared_ptr destructors are ever called. This doesn't matter so much if you're just allocating memory (if you don't catch somewhere you're going to terminate anyway), but it could matter if Foo were a lock file or some other persistent system resource that can outlive the process, or another service somewhere is waiting for a message on a timeout.
The alternative to relying on there being a try{} block somewhere up the stack is to add a function-try block on Bars constructor.
tl;dr: member destructors aren't called if you throw from a constructor init list, function-try blocks fix that.