C++ 超出范围后在Lambda中设置的共享指针

C++ 超出范围后在Lambda中设置的共享指针,c++,lambda,scope,shared-ptr,C++,Lambda,Scope,Shared Ptr,我在共享指针、lambda和范围方面有问题 我的情况是我有一个调用的方法,所以我可以稍后使用返回的值。在这里之前都很正常。当我在这个方法中有一个异步方法时,问题就来了,我必须对一个共享的\u指针创建一组异常。我使用lambda函数来处理来自这个异步方法的回调。在这个lambda中,我必须使用我的shared_指针并在其上设置一个异常(来自其类的方法)resultPtr->setException() 我首先在lambda中使用了一个共享的ptr,然后是一个弱的ptr(因为我在一些地方读到共享的p

我在共享指针、lambda和范围方面有问题

我的情况是我有一个调用的方法,所以我可以稍后使用返回的值。在这里之前都很正常。当我在这个方法中有一个异步方法时,问题就来了,我必须对一个共享的\u指针创建一组异常。我使用lambda函数来处理来自这个异步方法的回调。在这个lambda中,我必须使用我的shared_指针并在其上设置一个异常(来自其类的方法)resultPtr->setException()

我首先在lambda中使用了一个共享的ptr,然后是一个弱的ptr(因为我在一些地方读到共享的ptr可能导致内存泄漏)。但直到现在我想我真的需要使用共享的ptr

我必须测试是否在第二个.cpp中设置了此异常,因此我调用该方法并使用返回值。我让线程等待大约500毫秒,然后测试它是否有异常,但它没有。然而,在极少数情况下,它“有例外”。我可以看到lambda正在被调用,它通过我的日志设置了异常,但是它似乎没有更改我首先返回的值(好像它指向了另一个地方)

我提到的第一个方法的输入对于我的案例并不重要,只是它们是指针

在我的例子中,我有一些类似于:

file1.cpp
typedef shared_ptr<Result> ResultPtr;
ResultPtr method_name(TypePtr args)
{
    if(args != nullptr)
    {
        ResultPtr result = make_shared<Result>();
        stuff->callAsync([this, result](input)
        {
            if(result == nullptr)
            {
                result->setException();
            }
        });
    }
    else
    {
        result->setError();
    }
    return result;
}

file2.cpp
bool testingMethod()
{
    ResultPtr result = file1::methodName(TypePtr args)
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    test(result->hasException);
}
file1.cpp
typedef共享_ptr ResultPtr;
ResultPtr方法_名称(TypePtr args)
{
如果(args!=nullptr)
{
ResultPtr result=make_shared();
stuff->callAsync([this,result](输入)
{
如果(结果==nullptr)
{
结果->设置异常();
}
});
}
其他的
{
结果->设置错误();
}
返回结果;
}
file2.cpp
布尔测试方法()
{
ResultPtr result=file1::methodName(TypePtr args)
std::this_线程::sleep_for(std::chrono::毫秒(500));
测试(结果->异常);
}

为了进行测试,我使用了另一个类,在这个类中,我使用某些输入调用这个方法(这里不重要),我需要比较resultPtr的对象值。一旦它超出范围(返回a),我就不能再访问该对象了。调用此方法后,我让线程等待大约1秒,但它从不更改状态(因为它不能指向已销毁的对象)

有没有办法克服这个问题?其他建议


谢谢大家!

当然,您不能再访问该对象了,因为它是在对象离开创建它的
if(args)
块的范围时出现的。您需要让对象位于方法之外,例如。G将其存储为类成员或(禁止!)在全局变量中


您是否需要将其包装在共享指针中尚不清楚,您需要提供一个MCVE,并对其进行更清晰的描述。

当然,您不能再访问该对象,因为它是在离开创建它的
if(args)
块的范围时创建的。您需要让对象位于方法之外,例如。G将其存储为类成员或(禁止!)在全局变量中


您是否需要将其包装在共享指针中尚不清楚,您需要提供一个MCVE,并对其进行更清晰的描述。

如果您的
callAsync
确实是异步的,那么当局部变量
result
a
完全超出范围时,lambda可能会开始执行。您应该将所需的变量作为参数传递,例如作为绑定使用
std::bind

typedef shared_ptr<Result> ResultPtr;
ResultPtr method_name(args)
{
    if(args)
    {
        ResultPtr a = make_shared<Result>();
        std::weak_ptr<Result> result(a);
        stuff->callAsync(std::bind([this](std::weak_ptr<Result> result_param)
        {
            auto resultPtr = result_param.lock();
            if(resultPtr)
            {
                resultPtr->setValue()
                ...other stuff...
            }
        }, result));
    }
    else
    {
        a->setError();
    }
    return a;
}
typedef共享\u ptr ResultPtr;
ResultPtr方法_名称(args)
{
如果(args)
{
ResultPtr a=make_shared();
标准:弱ptr结果(a);
stuff->callAsync(std::bind([this](std::weak\u ptr result\u param)
{
auto resultPtr=result_param.lock();
if(resultPtr)
{
resultPtr->setValue()
…其他东西。。。
}
},结果);
}
其他的
{
a->setError();
}
返回a;
}

是的,您的示例令人困惑

如果您的
callAsync
确实是异步的,那么当局部变量
result
a
超出范围时,lambda可能会开始执行。您应该将所需的变量作为参数传递,例如作为绑定使用
std::bind

typedef shared_ptr<Result> ResultPtr;
ResultPtr method_name(args)
{
    if(args)
    {
        ResultPtr a = make_shared<Result>();
        std::weak_ptr<Result> result(a);
        stuff->callAsync(std::bind([this](std::weak_ptr<Result> result_param)
        {
            auto resultPtr = result_param.lock();
            if(resultPtr)
            {
                resultPtr->setValue()
                ...other stuff...
            }
        }, result));
    }
    else
    {
        a->setError();
    }
    return a;
}
typedef共享\u ptr ResultPtr;
ResultPtr方法_名称(args)
{
如果(args)
{
ResultPtr a=make_shared();
标准:弱ptr结果(a);
stuff->callAsync(std::bind([this](std::weak\u ptr result\u param)
{
auto resultPtr=result_param.lock();
if(resultPtr)
{
resultPtr->setValue()
…其他东西。。。
}
},结果);
}
其他的
{
a->setError();
}
返回a;
}

是的,您的示例令人困惑

如果您需要lambda来保证对象保持活动状态,为什么要使用弱指针来传递,而不是共享指针?弱指针的用途是您看到的行为,即它本身不能使对象保持活动状态

因为您只捕获弱指针,所以当唯一的共享指针超出范围时,如果在锁定弱指针之前它超出范围,它不会使共享指针保持活动状态。但是,您可以只捕获共享指针(通过值,因此获取一个副本),而不是使用弱指针。然后,引用计数将增加,lambda中的共享指针将使其保持活动状态,并且只有当两个共享指针都超出范围时,它才会被删除


像这样的共享所有权是共享指针的原因,只有当共享指针引用计数达到零时对象不再可访问时,才应该使用弱指针。

如果需要lambda来保证它保持