标准::函数复制参数

std::function copying parameters?

本文关键字:参数 复制 函数 标准      更新时间:2023-10-16

我的代码:

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

专用化std::function<R(Args...)>有一个调用运算符,其声明如下:

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

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

这是设计使然,事实上,如果A有一个移动构造函数,则只有一个副本,后跟一个移动构造 - 调用f(std::move(a))只会导致两个移动构造。如果你觉得两份副本太多了,你需要重新考虑foof是否都应该A而不是例如 A const&,和/或A是否可以有一个明智的移动构造函数。

您也可以在不修改foo的情况下执行std::function<void(A const&)> f = &foo;。但是,您应该保留这一点,以便在您无法控制的情况下修改foo和/或使A廉价移动可构造不是一种选择。在 C++11 中按值传递并没有错,所以我建议要么两者都应该A,要么两者都应该A const&

它被复制,因为你按值传递它。您可以通过将其作为 const 引用传递来避免所有副本。