C ++专家的问题:我有一个期望shared_ptr<T>
的库函数,我想在T
内调用此函数。我知道share_from_this
是正确的方法,但我无法理解它(以及如何正确使用它)。
我想出了一个技巧,我想知道它是否安全(没有UB)。如果不是,你能解释一下如何在我的案例中使用share_from_this
吗?
#include <memory>
template<class T>
void library_function(std::shared_ptr<T>)
{}
struct A {
std::shared_ptr<A> share()
{
return std::shared_ptr<A>(this, [](A*){});
}
void operator()()
{
library_function(share());
}
};
int main()
{
A a;
a();
}
答案 0 :(得分:2)
首先,您想要share_from_this
的对象需要以前是共享对象,并由std :: shared_ptr管理。确保允许它的类需要公开继承自std::enable_shared_from_this<A>
。接下来,如果要从中创建共享指针,则需要使用方法shared_from_this()
。
答案 1 :(得分:1)
您应该从std::enable_shared_from_this
派生您的课程。确保您的对象由std::shared_ptr
管理。
#include <memory>
template<class T>
void library_function(std::shared_ptr<T>)
{}
struct A : public std::enable_shared_from_this<A> {
void operator()()
{
library_function(shared_from_this());
}
};
int main()
{
auto a = std::make_shared<A>();
a->operator()();
}
答案 2 :(得分:1)
使用您当前的代码,它是安全的。
但是,如果library_function
存储shared_ptr
以后使用,a
因超出范围而被销毁。它的未定义行为。那不安全。此示例代码与您的代码没有太大区别,但在第二次调用中它具有未定义的行为:
template<class T>
void library_function(std::shared_ptr<T> t)
{
static std::shared_ptr<T> s;
if (!s) {
s = t;
}
if (s) s->do_something();
}
struct A {
std::shared_ptr<A> share()
{
return std::shared_ptr<A>(this, [](A*){});
}
void operator()()
{
library_function(share());
}
void do_something() {
}
};
int main()
{
// This emulates some function call and go out of scope
{
A a;
a();
}
// This call is undefined behavior
library_function(std::shared_ptr<A>{});
}
正确的方法是this:
#include <memory>
#include <iostream>
template<class T>
void library_function(std::shared_ptr<T> t)
{
static std::shared_ptr<T> s;
if (!s) {
s = t;
}
if (s) s->do_something();
}
struct A : std::enable_shared_from_this<A> {
~A() {std::cout << "Destructed\n"; }
std::shared_ptr<A> share()
{
return shared_from_this();
}
void operator()()
{
library_function(share());
}
void do_something() {
std::cout << "do_something\n";
}
};
int main()
{
// This emulates some function call and go out of scope
{
std::shared_ptr<A> a = std::make_shared<A>();
(*a)();
}
library_function(std::shared_ptr<A>{});
}
答案 3 :(得分:0)
您的课程应该来自std::enable_shared_from_this<>
,然后您可以致电this->shared_from_this()
获取shared_ptr<>
。
例如:
class foo : std::enable_shared_from_this<foo> {
public:
void bar() {
call_some_func(this->shared_from_this());
}
};
因此call_some_func()
将收到指向foo
实例的共享指针。这将起作用,因为原始实例已经在共享指针中,即实例创建为:
auto foo_inst = std::make_shared<foo>();