[英]Calling std::move() on derefrence value of smart pointer
class A{
public:
void AddObject(MsgType msg){
msg_queue.push_back(msg);
}
private:
std::queue<MsgType> msg_queue;
}
我有这个类A及其方法AddObject()
。 本课程有两种类型的客户。 第一种类型是他们仅获得boost::sharedPtr<MsgType>
而其他客户端具有std::shared_ptr<MsgType>
或const MsgType&
。
AddObject()
签名应该是什么,以便可以避免在此处进行转换或进行复制。 如果我使用AddObject(MsgType msg)
那么我将不得不从客户端调用:
boost::shared_ptr<MsgType> msg;
AddObject(std::move(*msg));
要么
std::shared_ptr<MsgType> msg;
AddObject(std::move(*msg));
我可以在AddObject()
使用std::move()
将其存储在队列中。 考虑到性能,这里的API应该是什么?
MsgType的大小约为1.4 MB,这是protobuf消息。 对于protobuf而言,移动构造函数非常昂贵。 所以看起来我不能使用std :: move在这里。
您最初编写AddObject()
的方式没有对输入MsgType
的所有权进行任何假设。 它不知道或不在乎MsgType
是如何分配的,或者谁应该拥有它。 在这种情况下,您唯一可以做的就是自己复制一份,这就是您当前正在执行的操作。
如果您希望AddObject()
在不进行复制的情况下取得所有权,则AddObject()
需要明确说明其期望如何管理所有权。 您可以通过以下两种方式之一表达所有权语义:
通过使用std::unique_ptr
(或boost::unique_ptr
)要求排他所有权:
class A{ public: void AddObject(std::unique_ptr<MsgType> msg){ msg_queue.push(std::move(*msg)); } private: std::queue<MsgType> msg_queue; };
或更好:
class A{ public: void AddObject(std::unique_ptr<MsgType> msg){ msg_queue.push(std::move(msg)); } private: std::queue<std::unique_ptr<MsgType>> msg_queue; };
通过使用std::shared_ptr
(或boost::shared_ptr
)共享所有权:
class A{ public: void AddObject(std::shared_ptr<MsgType> &msg){ msg_queue.push(msg); } private: std::queue<std::shared_ptr<MsgType>> msg_queue; };
否则,您真正能做的就是std::move()
输入MsgType
的内容 ,然后让调用者担心以后再释放MsgType
:
class A{
public:
void AddObject(MsgType &msg){
msg_queue.push(std::move(msg));
}
private:
std::queue<MsgType> msg_queue;
};
但是,根据您的情况,最后一种选择可能不太可行,因为您声称移动protobuf对象的成本很高。 在这种情况下,您应该只在指向protobuf对象的指针周围移动,而不是在对象本身周围移动。 这就是(std|boost)::unique_ptr
和(std|boost)::shared_ptr
起作用的地方。
如果要对类进行编码以支持std
和boost
智能指针,则必须为每种类型重载AddObject()
或为其提供一个模板参数,您可以根据需要专门处理该模板参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.