我正在使用 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 会复制这么多次?
- 将右值作为参数传递给绑定(bind)是否正确(在两种实现情况下)?
- 我是否理解正确,bind 会将对象移动到其上下文并存储它,并且当调用 foo 时,将其作为左值引用传递?
谢谢!
最佳答案
这是设计使然。
要避免这种情况,请避免复制绑定(bind)适配器并使用ref
:
auto f = boost::bind(&foo, boost::ref(t));
- 为什么 boost 会复制这么多次?
主要是因为您的构造函数无法被省略。将其保留为聚合或普通构造函数,这样就不会发生。
- 将右值作为参数传递给绑定(bind)是否正确(在两种实现情况下)?
是的,bind 按值捕获参数(除非您使用显式 ref()
或 cref()
来创建 reference_wrapper
。)
- 我是否理解正确,bind 会将对象移动到其上下文并存储它,并且当调用 foo 时,将其作为左值引用传递?
演示
<强> 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/