std :: function复制参数?

时间:2012-08-10 15:10:11

标签: c++ c++11 std-function

我的代码:

#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”两次。为什么对象被复制两次而不是一次?如何正确防止这种情况?

2 个答案:

答案 0 :(得分:9)

专精化std::function<R(Args...)>有一个带有以下声明的调用运算符:

R operator()(Args...) const;

在您的情况下,这意味着运营商需要A。因此,由于传值值语义,调用f(a)会产生副本。但是,基础foo目标也按值接受其参数。因此,当f的参数转发到foo时,会有第二个副本。

这是设计的,事实上如果A有一个移动构造函数,那么只有一个副本后跟一个移动构造 - 调用f(std::move(a))只会导致两个移动构造。如果您认为两份副本太多,则需要重新考虑foof是否应该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引用传递来避免所有副本。