假设我们有以下类:
Class MyClass
{
void func();
std::shared_ptr<std::function<void()>> getFuncPointer(); // returns pointer to func()
};
假设有一个其他类的对象(我们称之为objectB
)拥有MyClass
类型的对象(objectA
)的shared_ptr
,假设objectB
是objectA
的唯一所有者/用户,其他人都没有访问objectA
的权限。
按以下顺序发生的情况:
objectB
调用objectA->getFuncPointer()
并存储返回的shared_ptr
。objectB
呼叫objectA.reset()
问:objectA
的析构函数被调用了吗?
如果objectB
* 没有 *shared_ptr
到objectA
的方法之一,答案显然是肯定的。
我不确定的是objectB
获取一个shared_ptr
对objectA
的一个 * 方法 * 的影响。
如果回答为是:
如果objectA
被析构,但是另一个线程通过函数指针仍然在func()
中,那么如果我们访问一个成员变量会发生什么?看起来有问题,因为objectA
和它的成员沿着消失了。
如果回答为否:
看起来很有问题,因为我不明白一个成员函数的shared_ptr
如何可能保持整个对象的活动。函数指针对包含的对象一无所知,对吗?
这两种情况似乎都有问题,所以这就是为什么我不知道哪一个是正确的答案。
3条答案
按热度按时间qltillow1#
答案是肯定的:即使有
std::shared_ptr
间接地依赖于一个对象,它也可以被删除,通过创建一个std::shared_ptr
给一个给定的对象(这里是一个函数),只要它有一个共享的所有者,你就可以保留这个对象,所以你必须保证这个对象在这个时间内是有效的,如果你违背了这个承诺,事情就会出错。这和有一个对象 O1,它持有一个指向对象 O2的指针,然后在 O1还在的时候
delete
-ing O2没有什么区别,即使 *O *1本身是通过std::shared_ptr
持有的,也不能保留 O2。这两种情况似乎都有问题,所以这就是为什么我不知道哪一个是正确的答案。
与许多语言不同,C并不试图保证“安全”,编写调用 * undefined behavior * 的代码非常容易;在C中工作的一个重要部分就是避免这样做。
std::shared_ptr
是一个“帮助”您编写“安全”代码的工具,但它不会“阻止”您编写“不安全”代码。hgc7kmma2#
最有可能的是,它会被删除,根据上面的@ruakh给予的细节。
但是对象A可以通过对象B调用的
getFuncPointer
或其他方法来延长自己的生命周期,那就是getFuncPointer返回的std::函数是否捕获了示例本身。考虑使用enable_shared_from_this实现此实现
如果你有这个实现
上面的
a.reset()
调用将shared_ptr的引用计数减少1,但spFunc中仍有另一个未完成的引用。当spFunc
超出作用域并释放其捕获的变量时,对象a
最终将被删除。yquaqz183#
成员函数/方法通常在编译器中实现为全局函数,带有额外的第一个参数接收对象的示例,因此当引用
MyClass
的方法函数时,std::function <void()>
的类型实际上将是void (MyClass&)
/void (MyClass*)
[这就是为什么当您试图为成员函数创建std::bind
时,也将对象示例作为第一个参数传入]。通过返回
std::function<void()>
的shared_ptr
,您基本上是在为&MyClass::func()构造一个包含std::function<void(this)>
的shared_ptr
,它不拥有示例的实际所有权,所以答案是YES,shared_ptr
不应该阻止对象的销毁。编辑:我刚刚看到你的另一条评论,正如我所说的,这些方法和其他自由函数一样是函数,它们驻留在进程内存的CODE部分,它们不占用DATA内存,因此它们与对象的寿命无关,它们的一份拷贝(在每个翻译单元的正常情况下)将出现在那里,无论您创建1个
MyClass
对象还是10000个MyClass
对象,因此它们在程序的整个运行时都是可调用的