对分配给lambda的std :: function的访问冲突

时间:2017-09-29 12:42:42

标签: c++ function c++11 lambda

我试图使用std :: function和std :: bind来解决问题。我想构建一个通用结构,允许我将std :: function绑定到成员函数,而不必事先了解成员函数的参数。我写了这个东西

template<typename Class, typename Return, typename ...Args>
struct Caller
{
private:
    std::function<Return(Args ...)> callerFunction;

    Caller(const Caller&) = delete;
    Caller(Caller&&) = delete;
    Caller& operator=(const Caller&) = delete;

public:
    ~Caller() = default;
    Caller() = default;

    Caller(Class& instance, Return(Class::*function)(Args...))
    {
        callerFunction = [&](Args... args) { return (instance.*function)(args...); };
    }

    Return operator() (Args ... args)
    {
        return callerFunction(args...);
    }
};

仅供参考我知道函数的参数是通过值传递的(我使用带有可变参数模板的通用引用遇到了一些问题,我稍后会讨论它。)

这里的问题是,当我用operator()触发函数时,我收到了一个访问冲突错误。我试图缩小问题并创建一个没有可变参数的结构(允许成员函数只有一个int作为参数)我看到将lambda分配给std :: function给了我同样的错误,但是如果我用std :: bind和占位符一切都很好。

试验场就是这个

class A
{
public:
    bool foo(int a)
    {
        std::cout << a << std::endl;
        return true;
    }
};

int main()
{
    A a;
    a.foo(9);

    Caller<A, bool, int> caller(a, &A::foo);
    caller(10);

    std::cin.ignore();
}

使用lambda,我是否需要保存类的实例才能正确调用成员函数?

2 个答案:

答案 0 :(得分:2)

作为评论中的状态,你有悬空指针function,你可以改用:

Caller(Class& instance, Return(Class::*function)(Args...))
{
    callerFunction = [&instance, function](Args... args) {
        return (instance.*function)(std::forward<Args>(args)...);
    };
}

注意:instance也应该超过Caller

答案 1 :(得分:1)

当一个或多个对象的时间超过当前范围时,请不要使用[&]

您正在捕获对局部变量的引用并将它们存储在当前范围之外。