有没有办法检查std :: function是否指向有效对象的成员?

时间:2014-08-20 16:47:41

标签: c++ c++11 std-function stdbind c++14

让我证明一下我的意思。

#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

就像你期望的那样。

所以我的问题是,是否有任何方法可以确保在取消分配对象时我们无法调用该函数?这与使用智能指针无关,它与常规指针的工作方式相同。

3 个答案:

答案 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 ) );