我正在研究一种可以执行某种科学计算的库。
它旨在与GUI一起使用,因此计算是异步执行的,GUI(或任何将任务排入lib中的任何内容)将在先前指定的std::function
上接收回调。
那些回调应始终收到一个小的状态响应对象,即
struct StatusResponse {
StatusResponse(int respC, std::string respS): responseCode(respC),
responseString(std::move(respS)) {};
int responseCode;
std::string responseString;
};
这些回调是即发即弃的,它们不会返回任何内容(无效),也不需要等待回调执行的其他操作。 因此,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-references和智能指针,所以非常感谢任何帮助!
编辑: 我进行了一次测试,SergeyA似乎是正确的。 右值参考方式产生以下调试输出:
Constructor Called!
Copy Constructor Called!
Copy Constructor Called!
Destructor Called!
Destructor Called!
Callback called!
Called callback!
Exiting caller!
Exiting callback!
Destructor Called!
提供移动构造函数会导致Copy Constructor Called
替换为Move Constructor Called
答案 0 :(得分:0)
不,右值引用不正常 - 语句完成后将删除临时值。实际上,最有效的方法是按值复制,但在结构上使用移动构造函数,并从临时或std::move()
结果创建它。