Я пытаюсь выявить неприятную ошибку, из-за которой объект самопроизвольно повреждается, находясь внутри карты, и после нескольких часов отладки, я думаю, что я, возможно, не полностью осознал идею std :: shared_ptr .
Вот контекст :
Внутри метода я объявляю std :: shared_ptr и инициализирую его, чтобы он указывал на клон текущего объекта (созданный new ). Затем - после некоторых модификаций объекта - я вызываю тот же метод для этого указателя (рекурсивно).
Внутри следующей рекурсии метода принято решение вставить этот объект в std :: unordered_map (который является атрибутом класса, поэтому он доступен на всех уровнях рекурсии).
Это некоторый псевдокод для иллюстрации того, что я имею в виду:
class A
{
...
void DoSomething(void); // the recursive function
A* Clone(void) const { return new A(this); } // the clone method
...
static std::unordered_map<std::shared_ptr<A>,int> myMap{};
};
void A::DoSomething(void)
{
...
if (condition) myMap.insert({this,5}); // in a deeper recursive call, condition is true
...
std::shared_ptr<A> pA(Clone()); // make a copy
pA->... // modify it
pA->DoSomething(); // here is the recursive call
...
}
Проблема:
Иногда объект за указателем внутри std :: unordered_map уничтожается, и он кажется , как это происходит, когда исходный std :: shared_ptr выходит из области видимости.
Мое (предварительное) понимание: Вызов метода объекта, на который указывает std :: shared_ptr, не увеличивает счетчик ссылок - внутри вызываемого метода у меня есть доступ к this , то есть ptr, на который указывает std :: shared_ptr, но то, что я делаю с this , не влияет на исходный std :: shared_ptr.
Чтобы проверить это, я добавил код, чтобы сделать клон extra в дополнительный std :: shared_ptr, прямо в момент вставки в карту, а затем все работает нормально (только медленнее и использует удвоенную память) , что является проблемой - класс А имеет много сложных данных).
Вопрос: Правильно ли мое понимание? Если нет, как бы я вызвал метод std :: shared_ptr , чтобы this внутри метода по-прежнему оставался 'std :: shared_ptr'? Или это невозможно, и я должен использовать другой дизайн?
Относительно дубликатов: Должны ли мы передавать shared_ptr по ссылке или по значению? , кажется, указывает на этот путь, но о передаче параметров по значению или по ссылке, которая не является у меня есть выбор с указателем .