调用带有 unique_ptr 对象的函数
calling functions which take unique_ptr object
我有一个函数,其中回调接收一个 event
持有 data
的 unique_ptr 实例。我可以通过 event.data.get()
检索 char*
,这应该给我指针但不是所有权允许对象自由删除它。现在我有另一个函数,它采用 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 和移动语义非常混乱。
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
处于 "moved from" 状态,无法再访问数据。
void cbdata(DataEvent& event){
stream.write(std::move(event.data), event.length);
// now 'event.data' owns nothing and holds a null pointer
}
您的 stream.write
想要获得正在打印的事件的 片段 的所有权,这有点不寻常。它似乎拥有事件的一部分,而调用者仍然是其余部分的所有者。在那次调用之后,event
对象仍然不完整,因为 event.data
被送走了。
此外,您的 cbdata
通过 const&
接收事件。这是一个 "borrow & do not change" 语义。因此,它不应提供 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
class的其余部分,必须支持data
为nullptr的情况
请注意,这会更改 event
对象,它不是 const
函数。您的 cbdata
不适用于 const&
事件对象。
您还可以将数据复制到您的流中。如果数据很大,可能效率低下,但如果 DataType
可复制,则完全没问题。你可以这样做:
void cbdata(const DataEvent& event){
stream.write(std::make_unique<DataType>(*event.data),event.length);
}
与任何其他副本一样,您必须注意,当副本被销毁时,实际上只会删除复制的数据。不应删除原件和副本之间共享的任何内容。
我有一个函数,其中回调接收一个 event
持有 data
的 unique_ptr 实例。我可以通过 event.data.get()
检索 char*
,这应该给我指针但不是所有权允许对象自由删除它。现在我有另一个函数,它采用 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 和移动语义非常混乱。
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
处于 "moved from" 状态,无法再访问数据。
void cbdata(DataEvent& event){
stream.write(std::move(event.data), event.length);
// now 'event.data' owns nothing and holds a null pointer
}
您的 stream.write
想要获得正在打印的事件的 片段 的所有权,这有点不寻常。它似乎拥有事件的一部分,而调用者仍然是其余部分的所有者。在那次调用之后,event
对象仍然不完整,因为 event.data
被送走了。
此外,您的 cbdata
通过 const&
接收事件。这是一个 "borrow & do not change" 语义。因此,它不应提供 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
class的其余部分,必须支持data
为nullptr的情况请注意,这会更改
event
对象,它不是const
函数。您的cbdata
不适用于const&
事件对象。您还可以将数据复制到您的流中。如果数据很大,可能效率低下,但如果
DataType
可复制,则完全没问题。你可以这样做:void cbdata(const DataEvent& event){ stream.write(std::make_unique<DataType>(*event.data),event.length); }
与任何其他副本一样,您必须注意,当副本被销毁时,实际上只会删除复制的数据。不应删除原件和副本之间共享的任何内容。