Приведу простой пример, для илюстрации необходимости умных указателей.
Вот такой участок кода:
A* a = new A();
B* b = new B();
C* c = new C();
doSomething(a, b, c);
delete a;
delete b;
delete c;
небезопасен, если конструкторы могут кидать исключения.
Безопасныйый код выглядит примерно так:
A* a = new A();
B* b;
try {
b = new B();
} catch (...) {
delete a;
throw;
}
C* c;
try {
c = new C();
} catch (...) {
delete a;
delete b;
throw;
}
try {
doSomething(a, b, c);
} catch (...) {
delete a;
delete b;
delete c;
throw;
}
delete a;
delete b;
delete c;
что выглядит достаточно громоздко.
С использованием же умных указателей получится:
std::unique_ptr<A> a(new A());
std::unique_ptr<B> b(new B());
std::unique_ptr<C> c(new C());
doSomething(a.get(), b.get(), c.get());