auto sPointer = std::make_shared<Person>(*this); // problem here? makes a copy?
Да, std::make_shared
всегда создает новый объект. В этом случае он вызывает конструктор копирования Person
и создает новый, которым он может управлять.
Трудно предложить что-то без контекста. Вероятно, лучшее решение было предоставлено Р. Саху в этом ответе , но это можно было бы сделать без модификации интерфейса PersonListener
.
Одна вещь состояла бы в использовании обычного std::shared_ptr
конструктор, не предоставляя ничего не удаляющего:
auto sPointer = std::shared_ptr<Person>(this, [](auto){}); //custom deleter which does nothing to the object owned
Это решение, вероятно, приведет в замешательство людей - зачем использовать shared_ptr
, когда ничего не удается? С другой стороны, использование this
может быть подсказкой, почему это было сделано.
Если вы хотите получить функционал shared_ptr
изнутри класса, вы также можете рассмотрим enable_shared_from_this
.
class Person: public std::enable_shared_from_this<Person> {
private:
std::string name;
PersonListener listener;
public:
Person(std::string name, PersonListener listener) : name{name}, listener{listener} {};
void setName(std::string name) {
this->name = name;
auto sPointer = shared_from_this(); //get a shared_ptr to this
listener.nameChanged(sPointer);
}
}
Обратите внимание, что у этого подхода есть несколько недостатков:
- Объекты
Person
класса всегда необходимо создать как std::shared_ptr
(поэтому вы не можете, например, Person myPerson;
где-либо) - Вы не можете вызвать
shared_from_this()
в конструкторе, потому что родительский элемент shared_ptr
еще не существует. - Это может легко привести к циклическим зависимостям и утечкам памяти, которые не обнаруживаются многими инструментами (например,
valgrind
). Если PersonListener
сохранит указатель, полученный в качестве члена, ни один из объектов не будет удален.