Зачем нужны умные, мудрые и пр. указатели в С++

Рейтинг: 21Ответов: 3Опубликовано: 05.04.2011
  1. Зачем нужны эти самые умные, мудрые и пр. типы 'указателей'?
  2. В каких конкретно случаях нужно применять эти конкретные типы? В чем разница между ними?
  3. Имеет ли смысл самому реализовать эти концепции на практике или использовать готовые варианты из boost? В чем преимущество этих вариантов?

Ответы

▲ 12Принят
  1. Благодаря умным указателям можно избежать утечек памяти и обеспечить безопасное ее использование.
  2. Если честно, то нет таких ситуаций в которых не нужно было бы применять умных указателей. Вопрос скорее нужно поставить так - какой тип умного указателя нужно применить в той или иной ситуации?
  3. Всегда нужно начинать с готовых классов, но бывают ситуации когда подцеплять к проекту столь громоздкую библиотеку, как boost просто невозможно по техническим причинам. В таких ситуациях выручает собственный класс, но нужно понимать что это будет скорее всего частный случай реализации умного указателя и конкурировать с библиотечным типом он сможет только в этом проекте.
▲ 8

Приведу простой пример, для илюстрации необходимости умных указателей. Вот такой участок кода:

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());
▲ 5

Итак, получается, что умные указатели нужны, чтобы обойти ограничения, получаемые при использовании классических указателей C++. Преимущества использования умных указателей:

  1. Автоматическая инициализация.
  2. Автоматическая очистка.
  3. Отсутствие проблем с указателями на уже удаленные объекты.
  4. Умные указатели - exception safe
  5. С помощью умных указателей можно реализовать алгоритмы сборки мусора. Которые в С++ изначально отсутствуют.
  6. Возможность повысить эффективность кода при наличии доп. информации об объектах, на которые необходимо ссылаться