Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有没有一种意识形态的方式来避免这种赤裸裸的新的使用?_C++_Opencl_C++20 - Fatal编程技术网

C++ 有没有一种意识形态的方式来避免这种赤裸裸的新的使用?

C++ 有没有一种意识形态的方式来避免这种赤裸裸的新的使用?,c++,opencl,c++20,C++,Opencl,C++20,在我的应用程序中,我需要设置回调,回调的唯一责任是在单独的对象中更新与已完成事件关联的状态,以便以后可以查询它。然而,由于API是如何设计的,我不能保证在事件完成时另一个对象仍然是所有的,所以我需要存储一个指向该对象的指针,因为回调API是基于C的,所以我最终存储了一个指向智能指针的原始指针,这是我见过的最丑陋的代码* *在过去的几个小时里 这就是我为实现这一目标而写的: event.setCallback(CL_COMPLETE, [](cl_event event, cl_int, void

在我的应用程序中,我需要设置回调,回调的唯一责任是在单独的对象中更新与已完成事件关联的状态,以便以后可以查询它。然而,由于API是如何设计的,我不能保证在事件完成时另一个对象仍然是所有的,所以我需要存储一个指向该对象的指针,因为回调API是基于C的,所以我最终存储了一个指向智能指针的原始指针,这是我见过的最丑陋的代码*

*在过去的几个小时里

这就是我为实现这一目标而写的:

event.setCallback(CL_COMPLETE, [](cl_event event, cl_int, void* ptr) {
    auto ptr_ptr = static_cast<std::weak_ptr<render_future::shared_state>*>(ptr);
    if(auto shared_ptr = ptr_ptr->lock()) {
        auto & shared_state = *shared_ptr;
        std::lock_guard lock{ shared_state.mutex };
        shared_state.event_state[event] = true;
    }
    delete ptr_ptr;
}, new std::weak_ptr<render_future::shared_state>(future.state));
event.setCallback(CL_完成,[](CL_事件事件,CL_int,void*ptr){
自动ptr_ptr=静态(ptr);
如果(自动共享\u ptr=ptr\u ptr->lock()){
自动和共享\u状态=*共享\u ptr;
std::lock_guard lock{shared_state.mutex};
共享状态。事件状态[事件]=真;
}
删除ptr\u ptr;
},新标准::弱_ptr(future.state));
我特别反对我自己使用
new std::weak_ptr(future.state)
,这在我看来似乎是某种反模式:与智能指针一起使用裸
new
delete

然而,问题是,由于回调必须是函数指针,因此我的lambda表达式无法复制或引用其他对象,而在lambda中获取
共享状态
对象的唯一方法是传入其指针;同样,因为我不能保证它的生存期没有过期,所以我需要以指向
弱\u ptr
的指针的形式获取它,以便在(并且仅当)对象仍然存在时可以对其进行操作

所以最终,我的问题是:是否有一种意识形态的方式将
shared\u state
传递到这个回调中

  • 我可以检查以确保对象仍然存在,而
  • 还消除了我对裸
    新建
    删除
    调用的使用

  • 在lambda中,只需使用一个独特的\u ptr即可实现明显的改进:

    auto callback = [](cl_event event, cl_int, void* ptr) {
        std::unique_ptr<std::weak_ptr<render_future::shared_state>> ptr_ptr{ static_cast<std::weak_ptr<render_future::shared_state>*>(ptr)};
        if(auto shared_ptr = ptr_ptr->lock()) {
            std::lock_guard lock{ shared_state->mutex };
            shared_state->event_state[event] = true;
        }
    }
    
    auto callback=[](cl_事件事件,cl_int,void*ptr){
    std::unique_ptr ptr_ptr{static_cast(ptr)};
    如果(自动共享\u ptr=ptr\u ptr->lock()){
    std::lock\u guard lock{shared\u state->mutex};
    共享状态->事件状态[事件]=true;
    }
    }
    
    在创建方面,您可以使用
    std::unique\u ptr::release()

    auto ptr=std::使_唯一(future.state);
    setCallback(CL_COMPLETE,callback,ptr.release());
    

    但是,由于使用无捕获lambda调用C函数,这里并没有意外的异常需要保护,因此这是否是对当前操作的真正改进值得商榷。

    您可以在地图中存储指向对象的智能指针,并使用非拥有指针作为键。回调可以从映射中删除指针,从而释放所有权。映射必须比回调有效。如果需要,可以使用静态存储

    使用唯一所有权,您可以将对象本身直接存储在地图中


    在所有权唯一的情况下,数据结构跟踪分配的额外复杂性和开销是否值得去掉显式的new和delete是有争议的。对于共享所有权,这可能是一个更好的选择。

    我最终选择了第一个建议,而没有使用第二个。就我而言,
    ptr.release()
    只比裸体的
    new
    稍微安全一些,所以至少通过删除
    delete
    ,我觉得代码已经改进了。
    auto ptr = std::make_unique<std::weak_ptr<render_future::shared_state>>(future.state);
    
    event.setCallback(CL_COMPLETE, callback, ptr.release());