Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.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接口传递共享的_ptr* 我有一个C++项目,特别是SDL事件。我希望将事件系统用于传入的网络消息,就像它用于UI事件一样。我可以定义新的事件类型并附加一些任意数据(请参阅)。如果我使用普通指针,我会这样做: Uint32 message_event_type = SDL_RegisterEvents(1); /* In the main event loop */ while (SDL_Poll(&evt)) { if (evt.type == message_event_type) { Message *msg = evt.user.data1; handle_message(msg); } } /* Networking code, possibly in another thread */ Message *msg = read_message_from_network(); SDL_Event evt; evt.type = message_event_type; evt.user.data1 = msg; SDL_PostEvent(evt);_C++_Sdl_Shared Ptr - Fatal编程技术网

通过无效的C接口传递共享的_ptr* 我有一个C++项目,特别是SDL事件。我希望将事件系统用于传入的网络消息,就像它用于UI事件一样。我可以定义新的事件类型并附加一些任意数据(请参阅)。如果我使用普通指针,我会这样做: Uint32 message_event_type = SDL_RegisterEvents(1); /* In the main event loop */ while (SDL_Poll(&evt)) { if (evt.type == message_event_type) { Message *msg = evt.user.data1; handle_message(msg); } } /* Networking code, possibly in another thread */ Message *msg = read_message_from_network(); SDL_Event evt; evt.type = message_event_type; evt.user.data1 = msg; SDL_PostEvent(evt);

通过无效的C接口传递共享的_ptr* 我有一个C++项目,特别是SDL事件。我希望将事件系统用于传入的网络消息,就像它用于UI事件一样。我可以定义新的事件类型并附加一些任意数据(请参阅)。如果我使用普通指针,我会这样做: Uint32 message_event_type = SDL_RegisterEvents(1); /* In the main event loop */ while (SDL_Poll(&evt)) { if (evt.type == message_event_type) { Message *msg = evt.user.data1; handle_message(msg); } } /* Networking code, possibly in another thread */ Message *msg = read_message_from_network(); SDL_Event evt; evt.type = message_event_type; evt.user.data1 = msg; SDL_PostEvent(evt);,c++,sdl,shared-ptr,C++,Sdl,Shared Ptr,相反,到目前为止,我一直在使用shared\u ptr。消息一旦构建就成为只读对象,在处理时可能会在很多地方使用,所以我想对它们使用共享的ptr 我希望在网络端和事件处理端使用共享的ptr来处理消息。如果我这样做: // in networking code: shared_ptr<Message> msg = ... evt.user.data1 = msg.get(); // later, in event handling: shared_ptr<Message>

相反,到目前为止,我一直在使用
shared\u ptr
。消息一旦构建就成为只读对象,在处理时可能会在很多地方使用,所以我想对它们使用共享的ptr

我希望在网络端和事件处理端使用共享的ptr来处理消息。如果我这样做:

// in networking code:
shared_ptr<Message> msg = ...
evt.user.data1 = msg.get();

// later, in event handling:
shared_ptr<Message> msg(evt.user.data1);
//在网络代码中:
共享\u ptr msg=。。。
evt.user.data1=msg.get();
//稍后,在事件处理中:
共享的ptr消息(evt.user.data1);
然后有两个独立的共享ptr,其中任何一个都可以在消息对象仍在使用时删除它。我需要以某种方式通过SDL_UserEvent结构传递共享的ptr,该结构只有几个
void*
和int字段

附加。注意
SDL\u PostEvent
立即返回;事件本身被放入队列中。在消息的共享ptr超出网络代码的范围后,处理程序可能会从队列中弹出该事件。因此,我无法传递要从中复制的本地共享\u ptr的地址。当复制发生时,它可能不再有效


有没有人遇到过类似的问题并知道一个好的解决方案?

似乎是理想的使用场所

struct Message:std::从\u中启用\u共享\u
{
…
};
evt.user.data1=msg.get();
//此消息使用与上述消息相同的引用计数
shared_ptr msg=evt.user.data1.shared_from_this();

为共享ptr分配一个指针,该指针带有新的。这将调用构造函数(增加引用计数),但不会调用相应的析构函数,因此共享的ptr永远不会破坏它的共享内存

然后在相应的处理程序中,在复制共享的\u ptr后销毁该对象,使其引用计数恢复正常

这与通过消息队列传递任何其他非原语类型的方式相同

typedef shared_ptr<Message> MessagePtr;

Uint32 message_event_type = SDL_RegisterEvents(1);

/* In the main event loop */
while (SDL_Poll(&evt)) {
    if (evt.type == message_event_type) {
         // Might need to cast data1 to (shared_ptr<Message> *)
         unique_ptr<MessagePtr> data (evt.user.data1);
         MessagePtr msg = *data;
         handle_message(msg);
    }
}

/* Networking code, possibly in another thread */
MessagePtr msg = read_message_from_network();
SDL_Event evt;
evt.type = message_event_type;
evt.user.data1 = new MessagePtr (msg); 
SDL_PostEvent(evt);
typedef共享消息ptr;
Uint32消息事件类型=SDL注册事件(1);
/*在主事件循环中*/
while(SDL_民意测验和evt)){
if(evt.type==消息\事件\类型){
//可能需要将数据1强制转换为(共享\u ptr*)
唯一的ptr数据(evt.user.data1);
MessagePtr msg=*数据;
处理信息(msg);
}
}
/*网络代码,可能在另一个线程中*/
MessagePtr msg=从网络()读取消息;
SDL_事件evt;
evt.type=消息\事件\类型;
evt.user.data1=新消息ptr(msg);
SDL_事件后(evt);
消息在构造后是只读对象


我只想指出,这是好的,甚至是多线程安全所必需的。您可能想使用
shared\u ptr
我想到了另一种可能的技术:使用placement new将
shared\u ptr
存储在与C结构相同的空间中:

SDL_Event evt;
evt.type = event_type;
// create new shared_ptr, in the same memory as evt.user.code
new (&evt.user.code) shared_ptr<Message>(msg);
SDL_PushEvent(&evt);
SDL_事件evt;
evt.type=事件类型;
//在与evt.user.code相同的内存中创建新的共享ptr
新的(&evt.user.code)共享\u ptr(msg);
SDL_PushEvent(&evt);
然后SDL将事件作为C对象复制,直到稍后的代码从事件中提取消息:

shared_ptr<Message> get_message(SDL_Event& evt) {
    // copy shared_ptr out of evt
    shared_ptr<Message> msg = *reinterpret_cast<shared_ptr<Message> *>(&evt.user.code);
    // destroy shared_ptr inside the event struct
    (reinterpret_cast<shared_ptr<Message> *>(&evt.user.code))->~shared_ptr();
    return msg;
}
shared_ptr get_消息(SDL_事件和evt){
//从evt中复制共享的ptr
共享的\u ptr msg=*重新解释\u cast(&evt.user.code);
//销毁事件结构中的共享\u ptr
(reinterpret_cast(&evt.user.code))->~shared_ptr();
返回味精;
}
事件结构中有几个字段,它们应该有足够的空间用于共享\u ptr(请参阅)


我知道这有点老套。我希望能对该技术进行一些合理性检查。

相关问题:为什么要共享ptr,为什么不让另一个类创建和删除它们,并在需要时将它们作为引用传递?传递一个指向
共享ptr
的指针,并在接收函数中复制它的值。例如,
evt.user.data1=&msg
shared\u ptr msg=*reinterpret\u cast(evt.user.data1)
@JonathanPotter:看起来是一个很好的解决方案,可以在事件发布函数返回之前进行复制。但它不能。事件必须存在于队列中,当它被弹出时,它的原始共享\u ptr可能已经消失了。@Edmund:听起来你需要使用自己的引用计数系统,而不是依赖
共享\u ptr
(尽管如果ref计数可以按照下面@EyasSH的建议手动递增,那么从_共享_,这可能是一个选项)这将只适用于C++ 11和UP,但它是一个优雅的可维护的解决方案。@ QXYNN代码> STD::SyrdYPPTR <代码>是C++ 11和Up,由于某种原因,我在思考Booo::SypDypPTR。实际上OP没有指定命名空间,但可能是STD,在这种情况下,您的C++ 11解决方案非常适合。您可能还需要手动增量。在传递到C-land时输入引用计数,并在输出时将其递减。我认为这在shared_ptr中用作入侵指针时是可能的。当然在boost入侵指针中也是可能的。好的,终于弄明白了这是如何工作的。当第一个
msg
指针超出范围时,如何阻止消息被破坏er将其放入队列?我一直在试图弄清楚这是如何工作的。我不明白的是,分配了“new”的共享\u ptr对象是如何被解除分配的?
unique\u ptr
在if语句末尾解除分配的。或者(也许更清楚?)我可以使用一个原始指针,在if语句末尾调用
delete data
。我发现依靠
unique\ptr
编写正确的代码比
delete
更容易。谢谢,现在已经清楚了
shared_ptr<Message> get_message(SDL_Event& evt) {
    // copy shared_ptr out of evt
    shared_ptr<Message> msg = *reinterpret_cast<shared_ptr<Message> *>(&evt.user.code);
    // destroy shared_ptr inside the event struct
    (reinterpret_cast<shared_ptr<Message> *>(&evt.user.code))->~shared_ptr();
    return msg;
}