虽然在工作这个问题 ,我注意到,海湾合作委员会(V4.7)的执行std::function
时,他们采取的价值移动它的参数。 下面的代码显示了这种行为:
#include <functional>
#include <iostream>
struct CopyableMovable
{
CopyableMovable() { std::cout << "default" << '\n'; }
CopyableMovable(CopyableMovable const &) { std::cout << "copy" << '\n'; }
CopyableMovable(CopyableMovable &&) { std::cout << "move" << '\n'; }
};
void foo(CopyableMovable cm)
{ }
int main()
{
typedef std::function<void(CopyableMovable)> byValue;
byValue fooByValue = foo;
CopyableMovable cm;
fooByValue(cm);
}
// outputs: default copy move move
我们在这里看到的副本cm
的情况下(因为这似乎是合理的byValue
的参数采取值),但后来有两个动作。 由于function
上的拷贝操作cm
,即其移动它的参数这一事实可以看作是一个不重要的实现细节。 但是,这种行为会导致一些麻烦, 当使用function
一起bind
:
#include <functional>
#include <iostream>
struct MoveTracker
{
bool hasBeenMovedFrom;
MoveTracker()
: hasBeenMovedFrom(false)
{}
MoveTracker(MoveTracker const &)
: hasBeenMovedFrom(false)
{}
MoveTracker(MoveTracker && other)
: hasBeenMovedFrom(false)
{
if (other.hasBeenMovedFrom)
{
std::cout << "already moved!" << '\n';
}
else
{
other.hasBeenMovedFrom = true;
}
}
};
void foo(MoveTracker, MoveTracker) {}
int main()
{
using namespace std::placeholders;
std::function<void(MoveTracker)> func = std::bind(foo, _1, _1);
MoveTracker obj;
func(obj); // prints "already moved!"
}
由标准允许这种行为? 是std::function
允许移动它的参数? 如果是这样,这是正常的,我们可以通过转换返回的包装bind
成std::function
与价值的参数,即使使用占位符多次出现时,这会触发意外的行为?