我正在开发一个库,它将执行某种科学计算。它旨在与GUI一起使用,因此计算是异步执行的,并且图形用户界面(或将任务入队到库中的任何东西)将在先前指定的std::function上接收回调。这些回调应始终接收一个小的状态响应对象,即
struct StatusResponse {
StatusResponse(int respC, std::string respS): responseCode(respC),
responseString(std::move(respS)) {};
int responseCode;
std::string responseString;
};这些回调是即发即忘的,它们不返回任何东西(void),也不需要等待回调执行的另一个操作。因此,StatusResponse对象也是临时的。现在似乎有很多种方法可以去做。我的第一个想法是按如下方式定义回调函数
template<typename T0>
using Action = std::function<void(std::shared_ptr<T0>)>;它的名字就像
rdt::Action<rdt::StatusResponse> callback;
std::shared_ptr<rdt::StatusResponse> response =
std::make_shared<rdt::StatusResponse>
(rdt::errorcode::DEVICE_ID_OUT_OF_RANGE, std::string {"Device ID out
of Range!"});
callback(response);
return;这似乎非常低效和昂贵(使用std::shared_ptr进行即发即忘,而且程序需要返回库函数,只是为了返回...)现在我想出了另一种方法:
void callback(std::unique_ptr<StatusResponse> response);
std::unique_ptr<StatusResponse> response =
std::make_unique<StatusResponse>(0, "success!");
callback(std::move(response));然而,这似乎仍然是无效的,因为我正在围绕一个无论如何都会被销毁的对象构建一个包装器。
void callback(StatusResponse&& response);
StatusResponse response {0, "Success!"};
callback(std::move(response));是可能的,甚至是
callback(StatusResponse {0, "Success!"});所以,现在,我对这些可能性相当不确定。
第一个问题:结构中的std::move合适吗?
第二个问题:哪种解决方案将提供最佳的速度优势?回调可能会被这样调用
std::thread t(callback, StatusResponse {0, "Success!"});
t.detach();我刚刚开始学习rvalue引用和智能指针,所以非常感谢您的帮助!
编辑:我做了一个测试,SergeyA似乎是对的。rvalue引用方法产生以下调试输出:
Constructor Called!
Copy Constructor Called!
Copy Constructor Called!
Destructor Called!
Destructor Called!
Callback called!
Called callback!
Exiting caller!
Exiting callback!
Destructor Called!提供move构造函数会导致Move Constructor Called取代Copy Constructor Called
发布于 2017-03-21 03:15:00
不,右值引用不正常-语句完成后,临时引用将被删除。实际上,最有效的方法是按值复制,但在结构上使用move构造函数,并从临时或std::move()结果创建它。
https://stackoverflow.com/questions/42912031
复制相似问题