通过std::move将共享ptr作为参数传递的Boost asio post

通过std::move将共享ptr作为参数传递的Boost asio post,boost,std,bind,shared-ptr,stdmove,Boost,Std,Bind,Shared Ptr,Stdmove,我是新来助推的:asio。我需要将shared_ptr作为参数传递给handler函数 例如 boost::asio::post(std::bind(&::function_x,std::move(some_shared_ptr)) 使用std::move(一些共享)正确吗?或者我应该使用下面的 boost::asio::post(std::bind(&::function_x,some_shared_ptr)) 如果两者都正确,哪一个是可取的 提前谢谢 问候 ShankarBind按值存储参数

我是新来助推的:asio。我需要将shared_ptr作为参数传递给handler函数

例如

  • boost::asio::post(std::bind(&::function_x,std::move(some_shared_ptr))
  • 使用std::move(一些共享)正确吗?或者我应该使用下面的

  • boost::asio::post(std::bind(&::function_x,some_shared_ptr))
  • 如果两者都正确,哪一个是可取的

    提前谢谢

    问候
    Shankar

    Bind按值存储参数

    因此,两者都是正确的,可能是等价的。如果绑定后不使用
    某些参数,则将参数移动到绑定中可能更有效

    警告:高级用例 (如果需要,请跳过此选项)

    不是您所问的:如果
    函数\u x
    接受了右值引用参数会怎么样?

    很高兴你这么问。你不能。然而,您仍然可以通过左值引用接收数据,并从中移动。因为:

    rvalue引用仅用于指示可能从启用某些智能编译器优化和诊断的参数移动

    因此,只要您知道绑定函数只执行一次(!!),那么从左值参数移动是安全的

    在共享指针的情况下,实际上有更多的余地,因为从共享ptr移动实际上根本不会移动pointed-to元素

    所以,做一个小练习来演示这一切:

    #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!
    }
    
    #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
    }
    
    为什么要麻烦? 你为什么会关心以上这些?好吧,因为在Asio中有很多处理程序保证只执行一次,所以有时可以避免共享指针的开销(同步、控制块的分配、删除器的类型擦除)

    也就是说,您可以使用
    std::unique\u 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!
    }
    
    #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
    }
    
    这将在使用大量组合操作的代码中帮助很多:现在可以将操作的状态绑定到处理程序中,开销为零,即使它更大并且是动态分配的