提问人:Shankar R 提问时间:4/21/2021 更新时间:4/22/2021 访问量:366
使用 std::move 将共享 ptr 作为参数传递的提升 asio 帖子
Boost asio post with shared ptr passed as argument with std::move
问:
我是 boost:asio 的新手。我需要将shared_ptr作为参数传递给处理程序函数。
F.D.公司
- boost::asio::p ost(std::bind(&::function_x, std::move(some_shared_ptr)));
使用 std::move(some_shared_ptr) 是否正确?或者我应该使用下面,
- boost::asio::p ost(std::bind(&::function_x, some_shared_ptr));
如果两者都正确,哪一个是可取的?
提前致谢
问候 香卡
答:
1赞
sehe
4/21/2021
#1
Bind 按值存储参数。
所以两者都是正确的,而且可能是等价的。如果在绑定后不使用参数,则将参数移动到绑定中可能会更有效。some_argument
警告:高级用例
(如果你愿意,可以跳过这个)
不是你问的:如果function_x
采用右值引用参数怎么办?
很高兴你问。你不能。但是,您仍然可以通过左值引用接收,然后从中移动。因为:
右值引用仅用于指示可能从中移动的参数,从而启用一些智能编译器优化和诊断。
因此,只要您知道绑定函数只执行一次 (!!),那么从左值参数开始是安全的。
在共享指针的情况下,实际上有更多的回旋余地,因为从共享 ptr 移动实际上根本不会移动指向元素。
所以,一个小练习来演示这一切:
#include <boost/asio.hpp>
#include <memory>
#include <iostream>
static void foo(std::shared_ptr<int>& move_me) {
if (!move_me) {
std::cout << "already moved!\n";
} else {
std::cout << "argument: " << *std::move(move_me) << "\n";
move_me.reset();
}
}
int main() {
std::shared_ptr<int> arg = std::make_shared<int>(42);
std::weak_ptr<int> observer = std::weak_ptr(arg);
assert(observer.use_count() == 1);
auto f = std::bind(foo, std::move(arg));
assert(!arg); // moved
assert(observer.use_count() == 1); // so still 1 usage
{
boost::asio::io_context ctx;
post(ctx, f);
ctx.run();
}
assert(observer.use_count() == 1); // so still 1 usage
f(); // still has the shared arg
// but now the last copy was moved from, so it's gone
assert(observer.use_count() == 0); //
f(); // already moved!
}
指纹
argument: 42
argument: 42
already moved!
何苦?
你为什么要关心上述内容?好吧,由于在 Asio 中,您有很多保证精确执行一次的处理程序,因此您有时可以避免共享指针的开销(同步、控制块的分配、删除器的类型擦除)。
也就是说,您可以使用以下命令使用仅移动处理程序:std::unique_ptr<>
#include <boost/asio.hpp>
#include <memory>
#include <iostream>
static void foo(std::unique_ptr<int>& move_me) {
if (!move_me) {
std::cout << "already moved!\n";
} else {
std::cout << "argument: " << *std::move(move_me) << "\n";
move_me.reset();
}
}
int main() {
auto arg = std::make_unique<int>(42);
auto f = std::bind(foo, std::move(arg)); // this handler is now move-only
assert(!arg); // moved
{
boost::asio::io_context ctx;
post(
ctx,
std::move(f)); // move-only, so move the entire bind (including arg)
ctx.run();
}
f(); // already executed
}
指纹
argument: 42
already moved!
这将在使用大量组合操作的代码中提供很大帮助:您现在可以将操作的状态绑定到处理程序中,开销为零,即使它更大并且是动态分配的。
评论