让我证明一下我的意思。
#include <functional>
#include <iostream>
class MyClass
{
private:
int number;
public:
MyClass()
{
number = 0;
}
void printNumber()
{
std::cout << "number is " << number << std::endl;
number++;
}
};
int main()
{
std::shared_ptr<MyClass> obj = std::make_shared<MyClass>();
auto function = std::bind(&MyClass::printNumber, obj);
function();
// This deallocates the smart pointer.
obj.reset();
// This shouldn't work, since the object does not exist anymore.
function();
return 0;
}
输出:
number is 0
number is 1
如果我们像通常那样调用函数,则替换&#34; function()&#34;使用&#34; obj-&gt; printNumber()&#34;,输出为:
number is 0
Segmentation fault: 11
就像你期望的那样。
所以我的问题是,是否有任何方法可以确保在取消分配对象时我们无法调用该函数?这与使用智能指针无关,它与常规指针的工作方式相同。
答案 0 :(得分:6)
您的代码有效。
obj.reset()
不会释放共享的MyClass
对象,因为绑定表达式obj
中存在共享指针function
的副本。这是因为std::bind
复制(或移动)其参数,除非包含在reference_wrapper
中(例如std::ref
)。
如果您在MyClass
的析构函数上设置或设置断点,您会发现在main
结束时,当局部变量function
被破坏时,它不会被调用。 / p>
答案 1 :(得分:3)
有没有办法检查
std::function points
是否有效对象的成员?
std::function
未指向对象的&#34;成员&#34;,它封装了 Callable 。当您将其与对象绑定时,您将获得另一个可调用对象(实际上是未指定类型),可以存储在std::function
所以我的问题是,是否有任何方法可以确保在对象被解除分配时我们无法调用该函数?
不,没有办法。但正如ecatmur所指出的那样,由于std::bind
复制了它的论据,你的例子很好。
答案 2 :(得分:0)
&#34;这与使用智能指针无关,它与常规指针的工作方式相同。&#34;
这个说法不正确。具有智能指针的obj-&gt; printNumber()失败并不是因为对象被销毁,而是因为共享指针obj
的这个特定实例不再指向有效对象。如果您尝试使用原始指针执行此操作:
MyClass *obj = new MyClass;
auto function = std::bind(&MyClass::printNumber, obj);
function();
delete obj;
// This will have UB
function();
在销毁和内存释放后使用对象会得到完全不同的情况(未定义的行为)。
C ++中无法验证原始指针是否指向有效对象。但你可以使用的是std::weak_ptr
。它不能直接与std::bind
一起使用,因此您可能需要编写一个lambda或一个简单的包装器,您可以在其中检查该对象是否仍然有效:
auto wrapper = []( std::weak_ptr<MyClass> wobj ) { auto obj = wobj.lock(); if( obj ) obj->printNumber(); };
auto function = std::bind( wrapper, std::weak_ptr<MyClass>( obj ) );