2009-12-01 7 views
19

Рассмотрите следующий код.Как избежать утечки памяти с помощью shared_ptr?

using boost::shared_ptr; 
struct B; 
struct A{ 
    ~A() { std::cout << "~A" << std::endl; } 
    shared_ptr<B> b;  
}; 
struct B { 
    ~B() { std::cout << "~B" << std::endl; } 
    shared_ptr<A> a; 
}; 

int main() { 
    shared_ptr<A> a (new A); 
    shared_ptr<B> b (new B); 
    a->b = b; 
    b->a = a; 

    return 0; 
} 

Там не никакого вывода. Отсутствует дескриптор. Утечка памяти. Я всегда считал, что умный указатель помогает избежать утечек памяти.

Что делать, если мне нужны перекрестные ссылки в классах?

ответ

47

Если у вас есть круглые ссылки, подобные этому, один объект должен содержать weak_ptr другому, а не shared_ptr.

the shared_ptr introduction От:

Поскольку реализация использует подсчет ссылок, не будет утилизирован циклы shared_ptr экземпляров. Например, если main() держит shared_ptr к A, которые прямо или косвенно владеет shared_ptr обратно A, счет использования A «s будет 2. Разрушение оригинального shared_ptr оставит A болтая со счетчиком использования в 1. Использование weak_ptr к «перерыв циклов».

Спасибо, Глен, за ссылку.

+6

@Alexey, вот ссылка на документы, где она явно предупреждает об этой проблеме во введении. http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/shared_ptr.htm – Glen

+2

Какой? И почему бы не заменить обе слабые ссылки? Это нелепо. 'shared_ptr' использовался по какой-то причине. – curiousguy

+5

@curiousguy: Я не уверен, что понимаю ваш вопрос: что вы считаете смешным? Чтобы разбить цикл, вы должны заменить ссылку _one_ strong ссылкой на слабую ссылку; который полностью зависит от варианта использования. Вы не можете заменить все сильные ссылки слабыми ссылками, потому что тогда все объекты будут уничтожены, так как владельцев не осталось. –