Boost shared_from_this <>()
может кто-то кратко изложить несколько кратких слов о том, как следует использовать интеллектуальный указатель boost shared_from_this<>()
, особенно с точки зрения регистрации обработчиков в io_service с использованием функции bind.
ИЗМЕНИТЬ: В некоторых ответах был задан дополнительный контекст. В принципе, я ищу "gotchas", встречное интуитивное поведение, которое люди наблюдали с использованием этого механизма.
Ответы
Ответ 1
Самый большой "gotcha", с которым я столкнулся, - это незаконность вызова shared_from_this из конструктора. Это следует непосредственно из правила, согласно которому shared_ptr для объекта должен существовать, прежде чем вы сможете вызвать shared_from_this.
Ответ 2
Из моего понимания, иногда в вашем коде вы хотите, чтобы класс предлагал shared_ptr
себе, чтобы другие части вашего кода могли получить shared_ptr для объекта вашего класса после его создания.
Проблема в том, что если ваш класс просто имеет shared_ptr<>
для себя как переменную-члена, он никогда не будет автоматически разрушен, так как всегда существует "одна последняя ссылка", которая висит вокруг себя. Наследование из enable_shared_from_this
дает вашему классу автоматический метод, который возвращает не только shared_ptr
, но и содержит только слабый общий указатель в качестве переменной-члена, чтобы не влиять на счетчик ссылок. Таким образом, ваш класс будет освобожден, как обычно, когда последняя ссылка на него исчезнет.
Я никогда не использовал его, но это мое понимание того, как это работает.
Ответ 3
shared_from_this<>
используется, если объект хочет получить доступ к shared_ptr<>
, указывающему на себя.
Обычно объект знает только о неявном указателе this
, но не о каком-либо shared_ptr<>
управлении им. Кроме того, this
не может быть легко преобразован в shared_ptr<>
, который разделяет владение с другими существующими экземплярами shared_ptr<>
, поэтому нет простого способа для объекта получить действительный shared_ptr<>
для себя.
shared_from_this<>
можно использовать для решения этой проблемы. Например:
struct A : boost::enable_shared_from_this<A> {
server *io;
// ...
void register_self() {
io->add_client(shared_from_this());
}
};
Ответ 4
Документация boost::asio::io_service
destructor объясняет это довольно хорошо
Описанная последовательность разрушения выше позволяет программам упростить их управление ресурсами путем использования shared_ptr < > . Где объект время жизни привязано к времени жизни соединение (или некоторая другая последовательность асинхронные операции), shared_ptr к объекту будут связаны с обработчики для всех асинхронных связанные с ним операции. Эта работает следующим образом:
- Когда одно соединение заканчивается, все связанные асинхронные операции полный. Соответствующий обработчик объекты уничтожаются, и все Ссылки shared_ptr на объекты уничтожены.
- Чтобы завершить работу всей программы, вызывается функция stop() io_service прекратить любые вызовы run() насколько это возможно. Деструктор io_service определенный выше, уничтожает все обработчики, вызывая все ссылки shared_ptr все объекты подключения уничтожены.
Обычно ваши объекты связывают асинхронные операции, когда обработчики привязаны к функциям-членам с помощью boost::bind
и boost::shared_from_this()
. Есть несколько примеров, которые используют эту концепцию.
Ответ 5
Материал отсутствует в некоторых комментариях выше. Вот пример, который мне помог:
Увеличить enable_shared_from_ в этом примере
Для меня я боролся с ошибками о плохих слабых указателях. Вы ДОЛЖНЫ разместить свой объект в виде shared_ptr:
class SyncSocket: public boost::enable_shared_from_this<SyncSocket>
И выделите один из них следующим образом:
boost::shared_ptr<SyncSocket> socket(new SyncSocket);
Тогда вы можете сделать что-то вроде:
socket->connect(...);
Множество примеров показывают, как использовать shared_from_this() примерно так:
boost::asio::async_read_until(socket, receiveBuffer, haveData,
boost::bind(&SyncSocket::dataReceived, shared_from_this(), boost::asio::placeholders::error));
Но мне не хватало использовать shared_ptr для выделения объекта для начала.