gpt4 book ai didi

c++ - `std::function` 是否允许移动其参数?

转载 作者:IT老高 更新时间:2023-10-28 22:13:59 30 4
gpt4 key购买 nike

在处理 this question 时,我注意到 GCC (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 的参数是按值获取的),但随后有两个 Action 。由于 function 是在 cm 的拷贝上运行的,因此它移动其参数的事实可以被视为一个不重要的实现细节。但是,这种行为会引起一些麻烦 when using function together with 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 是否正常,即使这会在处理时触发意外行为有多次出现的占位符?

最佳答案

std::function指定将提供的参数传递给带有 std::forward 的包装函数.例如对于 std::function<void(MoveTracker)> , 函数调用运算符等价于

void operator(CopyableMovable a)
{
f(std::forward<CopyableMovable>(a));
}

自从 std::forward<T>相当于 std::moveT不是引用类型,这说明了您的第一个示例中的一个 Action 。第二个可能是因为必须通过 std::function 内部的间接层。 .

这也说明了您在使用 std::bind 时遇到的问题。作为包装函数:std::bind 指定转发其参数,在这种情况下,它被传递一个右值引用,该引用由 std::forward 产生。内呼std::function .因此,绑定(bind)表达式的函数调用运算符将​​右值引用转发给每个参数。不幸的是,由于您重用了占位符,因此在两种情况下它都是对同一对象的右值引用,因此对于可移动类型,无论哪个先构造都会移动值,而第二个参数将获得一个空壳。

关于c++ - `std::function` 是否允许移动其参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10008503/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com