我有一个函数,其中回调函数接收一个event
并拥有一个unique_ptr实例的data
。我可以通过char*
检索event.data.get()
,这应该给我指针,但没有所有权,允许对象自由删除它。现在,我有了另一个函数,该函数采用otherdata
的unique_ptr实例,并且当然可以管理所有权,因此该函数可以自由地释放它。
因此,我尝试从回调中获取data
并将其传递到安全获取otherdata
的函数中。
void cbdata(const DataEvent& event){
char* datatobewritten = event.data.get();
stream.write(std::move(datatobewritten),event.length));
}
上面的示例似乎确实有效,但是我不确定这是否是正确的方法。活动是否放弃所有权?如果是这样,放弃所有权是否安全?
为什么会导致编译器错误:Call to implicitly-deleted copy constructor of 'std::unique_ptr<char []>'
?
void cbdata(const DataEvent& event){
stream.write(event.data,event.length);
}
如果event.data给我一个unique_ptr,而stream.write得到一个unique_ptr,那么以上代码不能正常工作吗? 还是这个
stream.write(std::move(event.data), event.length);
很抱歉,我的C ++知识确实很有限,因此unique_ptr和move语义非常混乱。
答案 0 :(得分:2)
您的stream.write
想要获得其正在打印的事件的片段的所有权有点不寻常。看来它需要事件的一部分所有权,而调用者仍是其余事件的所有者。调用之后,event
个对象仍然不完整,因为event.data
被放弃了。
此外,您的cbdata
通过const&
参加比赛。这是“借用且不要更改”的语义。因此,它不应授予event
或其任何部分的所有权。
一些选项:
将整个事件的所有权传递给stream
,而不仅仅是data
。不过,您的cbdata
需要首先获取所有权。
请勿授予stream
任何所有权。通常,流仅用于向用户呈现数据,而不以任何方式对其进行操作。
更改事件,使其可以永久释放其data
。您将需要以下内容:
std::unique_ptr<DataType> Event::releaseData() {
return std::move(this->data);
//after the call, this->data is 'nullptr'!
}
当然,在其他Event
类中,必须支持data
为nullptr的情况。
请注意,这将更改event
对象,而不是const
函数。您的cbdata
无法在const&
事件对象上使用。
您还可以复制数据到流中。如果数据量大,可能效率不高,但是如果DataType
是可复制的,则完全可以。您可以这样做:
void cbdata(const DataEvent& event){
stream.write(std::make_unique<DataType>(*event.data),event.length);
}
与任何其他副本一样,您必须注意,当副本被销毁时,实际上仅删除了复制的数据。在原件和副本之间共享的任何东西都不应删除。
答案 1 :(得分:1)
stream.write()
可能需要一个const char *
,如果这样的话,您将不需要std::move()
来将数据传递给它。当您需要更改unique_ptr的数据所有权时,使用std::move()
。但是在这种情况下,event
拥有数据,我们只是暂时让stream.write()
对其进行访问。
void cbdata(const DataEvent& event){
const char* datatobewritten = event.data.get();
stream.write(datatobewritten, event.length);
}
如果stream.write()
取std::unique_ptr
,那么您需要std::move()
的数据从event.data
到此函数。移动之后,event.data
处于“已移出”状态,并且无法再访问数据。
void cbdata(DataEvent& event){
stream.write(std::move(event.data), event.length);
// now 'event.data' owns nothing and holds a null pointer
}