我正在使用boost::bind(Boost 1.64.0和gcc 8.3.0)创建一个可调用对象,并注意到了一个有趣的功能
传入绑定(bind)构造函数作为可包装函数的参数的对象被多次复制。
即使对象包装在std::move()中。虽然std::bind可以正常工作。
例:

#include <iostream>
#include <boost/bind.hpp>
#include <functional>

class Test
{
public:
    Test()
    {
        std::cout << "Create\n";
    }

    Test(const Test& rhs)
    {
        std::cout << "Copy\n";
    }

    Test(Test&& rhs)
    {
        std::cout << "Move\n";
    }

    ~Test() noexcept
    {

    }
};

void foo(Test& t)
{

}


int main()
{
    Test t;
    auto f = boost::bind(&foo, t);
    f();
}

boost::bind(&foo,t);的输出
Create
Copy
Copy
Copy
Copy
Copy

boost::bind(&foo,std::move(t))的输出;
Create
Move
Copy
Copy
Copy
Copy

std::bind(&foo,t);的输出
Create
Copy

std::bind(&foo,std::move(t))的输出;
Create
Move
  • 为什么boost复制会如此多次?
  • 将rvalue作为要绑定(bind)的参数传递正确吗(在两种实现方式中)?
  • 我是否正确理解bind会将对象移动到其上下文并存储它,并且在调用foo时将其作为左值引用传递?

  • 谢谢!

    最佳答案

    那是设计使然。

    为了避免这种情况,请避免绑定(bind)适配器的副本,并使用ref:

    auto f = boost::bind(&foo, boost::ref(t));
    

  • 为什么boost复制会如此多次?

  • 主要是因为您的构造函数无法被忽略。使其保持聚合或琐碎的构造,并且不会发生。
  • 将rvalue作为要绑定(bind)的参数传递正确吗(在两种实现方式中)?

  • 是的,bind通过值捕获参数(除非您使用显式的ref()cref()创建reference_wrapper。)
  • 我是否正确理解bind会将对象移动到其上下文并存储它,并且在调用foo时将其作为左值引用传递?

  • Yes

    演示版

    Live On Coliru
    #include <boost/bind.hpp>
    #include <functional>
    #include <iostream>
    
    struct Test {
        Test()                       { std::cout << "Create\n"; }
        Test(const Test& /*unused*/) { std::cout << "Copy\n";   }
        Test(Test&& /*unused*/)      { std::cout << "Move\n";   }
        ~Test() noexcept             {                          }
    };
    
    void foo(Test& /*unused*/) {}
    
    int main() {
        Test t;
        auto f = boost::bind(&foo, boost::ref(t));
        f();
    }
    

    打印品:
    Create
    

    关于c++ - boost::bind()创建参数的许多拷贝,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61409565/

    10-11 22:53
    查看更多