Могу ли я проверить, безопасно ли вызывать `shared_from_this`?

При звонке shared_from_this из типов, которые наследуются от enable_shared_from_this, очень плохие вещи (ТМ) могут случиться, если this в настоящее время не проводится shared_ptr объект (обычно сбой приложения). Можно ли в C ++ 14 (не 17) проверить, безопасно ли это?

Редактировать: не использовать исключения или попробовать / поймать.

0

Решение

Это деталь реализации, но не могли бы вы сделать что-нибудь неприятное с внутренней декларацией друга:

template<typename _Tp1>
friend void
__enable_shared_from_this_helper(const __shared_count<>& __pn,
const enable_shared_from_this* __pe,
const _Tp1* __px) noexcept

Реализуйте свою собственную версию с _Tp1 как weak_ptr<> *, который возвращает слабый указатель [На самом деле не совсем так, как __px является указателем const, поэтому вам нужно дополнительное косвенное обращение, чтобы потерять const, или, если вы все равно пачкаетесь, отбросьте его!] , Оберните все это в класс, из которого вы потом производите вместо enable_shared_from_this:

#if >= C++17
using enable_shared_from_this_c17 = enable_shared_from_this;
#else

template<typename _Tp>
enable_shared_from_this_c17: public enable_shared_from_this<_Tp>
{

weak_ptr<_Tp> weak_from_this()
{
weak_ptr<_Tp> rv; auto rv2 = &rv;
__enable_shared_from_this_helper(*(const __shared_count<>*)nullptr, this, &rv2);
return rv;
}
}
#endif

Теперь у вас есть реализация weak_from_this () в c ++ 14. Да, это противный клочок, но это только до тех пор, пока вы не обновитесь до 17.

Или просто поймайте исключение!

Третий вариант — добавить инстанцирующий шаблон-оболочку, которая устанавливает «сконструированный» в оболочке для enable_shared_from_this, который оборачивает shared_from_this (), поэтому он завершается ошибкой до тех пор, пока не будет установлен составной флаг.

enable_shared_from_this
safe_shared_from_this
your interfaces
your_implementation
constructed<your_implementation>

Конечно, это несовершенно, если класс когда-либо используется без немедленного присвоения shared_ptr.

1

Другие решения

Если какой-либо другой объект в вашей программе имеет доступ к необработанному объекту this указатель, то вы используете shared_ptr совершенно неверный путь.

Любой указатель на ваш объект для внешнего использования ДОЛЖЕН быть помещен в shared_ptr<YourObject> значение экземпляра, без исключений.

1

Если this не проводится shared_ptr тогда ты ничего не сможешь сделать. Из контекста: Разрешается вызывать shared_from_this только для ранее общего объекта, то есть для объекта, управляемого std :: shared_ptr. Вот пример этого:

#include <memory>

class MyClass;

std::shared_ptr<MyClass> global;

void resetGlobal()
{
global = std::make_shared<MyClass>();
}

class MyClass : public std::enable_shared_from_this<MyClass>
{
public:
void use()
{
resetGlobal();
shared_from_this();
}
};

int main()
{
global = std::make_shared<MyClass>();
global->use();
return 0;
}

В начале use метод shared_from_this должно быть хорошо (за исключением многопоточной среды без мьютексов), но после вызова любой функции, которая может изменить shared_ptrВ другом месте вы не можете быть уверены. После звонка resetGlobal функция this просто уничтожается, и любой доступ к нему является неопределенным поведением, поэтому может привести к ошибке сегментации.

Единственный способ убедиться, что через весь вызов метода shared_from_this действует, чтобы сделать временный shared_ptr в начале разговора:

void use()
{
std::shared_ptr<MyClass> tmp = shared_from_this();
resetGlobal();
shared_from_this();
}

или же

{
std::shared_ptr<MyClass> tmp = global;
global->use();
}
0
По вопросам рекламы [email protected]