繁体   English   中英

在智能指针的反引用值上调用std :: move()

[英]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起作用的地方。

如果要对类进行编码以支持stdboost智能指针,则必须为每种类型重载AddObject()或为其提供一个模板参数,您可以根据需要专门处理该模板参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM