在智能指针的反引用值上调用 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()
.此类有 2 种类型的客户端。第一种类型是他们只得到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()
,或者为其提供一个可以根据需要专门处理的模板参数。
- 为什么 std::unique 不调用 std::sort?
- std::cout.imbue()多重调用
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 我收到以下错误:抛出'std::bad_alloc'实例后终止调用
- 从类型std::函数传递变量失败,尽管调用方期望的类型完全相同
- 如果 std::vector::clear() 不是静态的,如何在没有实例的情况下调用它?
- 绑定派生类方法C++从实例范围之外的分隔 std::function 变量调用
- 使用 std::variant<...时调用 BaseState 函数而不是派生函数>
- 类型擦除的std::function与虚拟函数调用的开销
- 如何调用存储在指向"std::函数"的指针中的 lambda?
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 将参数打包的参数传递到 std::queue 中,以便稍后使用不同的函数调用
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- std::调用,未找到匹配的重载函数
- 线程 std::调用未知类型,无法专门化函数错误
- 如何使用 std:: 调用函数中的函数?
- 使用经典重载解析规则创建依赖于 std::调用的重载集类
- std::调用 end() 时出现多映射错误
- std::调用函数时找不到函数构造函数
- std::调用没有匹配的重载函数在VS 2015中发现错误