我的代码:
#include <iostream>
#include <functional>
using namespace std;
struct A {
A() = default;
A(const A&) {
cout << "copied A" << endl;
}
};
void foo(A a) {}
int main(int argc, const char * argv[]) {
std::function<void(A)> f = &foo;
A a;
f(a);
return 0;
}
我在控制台上看到“复制A”两次。为什么对象被复制两次而不是一次?如何正确防止这种情况?
答案 0 :(得分:9)
专精化std::function<R(Args...)>
有一个带有以下声明的调用运算符:
R operator()(Args...) const;
在您的情况下,这意味着运营商需要A
。因此,由于传值值语义,调用f(a)
会产生副本。但是,基础foo
目标也按值接受其参数。因此,当f
的参数转发到foo
时,会有第二个副本。
这是设计的,事实上如果A
有一个移动构造函数,那么只有一个副本后跟一个移动构造 - 调用f(std::move(a))
只会导致两个移动构造。如果您认为两份副本太多,则需要重新考虑foo
和f
是否应该A
而不是{}} A const&
,和/或A
是否可以拥有合理的移动构造函数。
您也可以在不修改std::function<void(A const&)> f = &foo;
的情况下执行foo
。但是,对于修改foo
超出您的控制范围并且/或使A
便宜地移动可构造的情况,您应该保留该选项。 C ++ 11中的passing by value没有任何问题,所以我建议两者都应该A
,或者两者都应该A const&
。
答案 1 :(得分:1)
它被复制,因为你按值传递它。您可以通过将其作为const引用传递来避免所有副本。