Что значит создать shared_ptr
для объекта?Это означает, что владелец shared_ptr
теперь принимает на себя владение объектом.Право собственности означает, что объект будет удален, когда он этого пожелает.Когда владелец shared_ptr
уничтожает его shared_ptr
, это может привести к потенциальному уничтожению объекта, при условии, что для этого объекта нет других shared_ptr
s.
Когда shared_ptr
член класса, это означает, что время жизни объекта, на которое указывает shared_ptr
, равно по крайней мере , пока объект, членом которого является shared_ptr
.Когда shared_ptr
находится в стеке, это означает, что время жизни объекта, на который указывает shared_ptr
, будет, по крайней мере, столько же, сколько и область, в которой он был создан. Как только объект падает со стека, он можетбыть удаленным.
только раз, когда вы должны взять указатель и заключить его в shared_ptr
, это когда вы выделяете объект изначально .Зачем?Потому что объект не знает, находится ли он в shared_ptr
или нет.Это не может знать.Это означает, что человек, создавший оригинал shared_ptr
, теперь обязан передать его другим людям, которым необходимо разделить права собственности на эту память.Единственный способ совместного владения - через конструктор копирования из shared_ptr
.Например:
shared_ptr<int> p1 = new int(12);
shared_ptr<int> p2 = p1.get();
shared_ptr<int> p3 = p1;
Конструктор копирования shared_ptr
создает общее владение между p1
и p3
.Обратите внимание, что p2
не делит владельца с p1
.Они оба думают, что владеют одной и той же памятью, но это не то же самое, что делиться ею.Потому что они оба думают, что они владеют уникальным владельцем.
Поэтому, когда три указателя будут уничтожены, произойдет следующее.Во-первых, p3
будет уничтожено.Но поскольку p3 и p1 совместно владеют целым числом, оно не будет уничтожено.Далее p2
будет уничтожено.Поскольку он думает, что он является единственным владельцем целого числа, он затем уничтожит его.
В этот момент p1
указывает на удаленную память.Когда p1
уничтожено, оно думает, что оно является единственным держателем целого числа, поэтому оно уничтожит его.Это плохо , так как оно уже было уничтожено.
Ваша проблема заключается в следующем.Вы находитесь в экземпляре класса.И вам нужно вызвать некоторые из ваших функций, которые занимают shared_ptr
.Но все, что у вас есть, это this
, который является обычным указателем.Что вы делаете?
Вы получите несколько примеров, которые предлагают enable_shared_from_this
.Но рассмотрим более актуальный вопрос: «почему эти функции принимают shared_ptr
в качестве аргумента?»
Тип указателя, который принимает функция, указывает на то, что эта функция делает со своим аргументом.Если функция принимает shared_ptr
, это означает, что ей нужно иметь указатель.Это должно взять общее владение памятью.Итак, посмотрите на ваш код и спросите, действительно ли эти функции нуждаются , чтобы стать владельцем памяти.Хранят ли они shared_ptr
где-то в течение длительного времени (то есть: в объекте), или они просто используют их во время вызова функции?
Если это последнее, то функции должны приниматьголый указатель, а не shared_ptr
.Таким образом, они не могут претендовать на право собственности.В этом случае ваш интерфейс самодокументируется: тип указателя объясняет владение.
Однако возможно, что вы вызываете функции, которые действительно должны принять совместное владение.Тогда вам нужно использовать enable_shared_from_this
.Во-первых, ваш класс должен быть получен из enable_shared_from_this
.Затем в функции:
void ClassName::LocalMethod()
{
boost::shared_ptr<ClassName> classNamePtr(shared_from_this());
//some operation with classNamePtr
return;
}
Обратите внимание, что здесь есть стоимость.enable_shared_from_this
ставит boost::weak_ptr
в классе.Но нет виртуальных накладных расходов или чего-то подобного;это не делает класс виртуальным.enable_shared_from_this
- это шаблон, поэтому вы должны объявить его следующим образом:
class ClassName : public boost::enable_shared_from_this<ClassName>