【问题标题】:Avoiding lambda copies in c++在 C++ 中避免 lambda 副本
【发布时间】:2015-11-05 20:23:05
【问题描述】:

我需要通过 MyClass2 将用户定义的 lambda 传递给 MyClass1。我想确保只有一个动作,没有副本。下面的代码是否实现了这一点?有没有更好的方法来做到这一点(比如使用编译器完成的隐式移动)?

注意:我可以控制 MyClass1 和 MyClass2

#include <functional>

using MyFunction = std::function<int(int)>;

class MyClass1 {
 public:
   MyClass1(const MyFunction& func): mFunc(std::move(func)) {}

 private:
   MyFunction mFunc;
};

class MyClass2 {
 public:
  MyClass1* getClass1(const MyFunction& func) {
    return new MyClass1(func);
  }
};

int main() {
  MyClass2 cl2;

  const auto& f = [] (int i) { return i; };

  MyClass1* cl1 = cl2.getClass1(f);
}

【问题讨论】:

  • 你不能移动一个常量引用
  • @bolov 但它似乎编译得很好。
  • 你可以std::move const,但它通常什么都不做 除了使用时的副本。它是const,你不能剥去它的内脏,std::move 只是将某些东西标记为“安全地剥去内脏”。额外的移动很便宜:在你写的任何地方用MyFunction替换const MyFunction&amp;。将MyClass1(func) 替换为MyClass1(std::move(func))
  • @Lol4t0 std::function 要求可调用它的包装是可复制构造的,你的不是因为只有移动类型。捕获可复制类型的 Lambda 是可复制的,可以存储在 std::function
  • @vikky.rk 摆脱了f 上的const&amp;move 无论如何。您的代码(如上所述)已经复制了f,因为f 不是 std::function,它是一个lambda。 Lambda 不是 std::functions,std::functions 不是 lambda。 move 将其放入 std::function 中将消除您的 std::function&lt;?&gt; const&amp; 案例和我的 std::function&lt;?&gt; 案例中的副本(并用移动替换它)。

标签: c++ function c++11 lambda


【解决方案1】:

由于您可以更改MyClass1MyClass2,因此您可以通过右值引用获取该函数,然后move 将其沿用

#include <functional>

using MyFunction = std::function<int(int)>;

class MyClass1 {
 public:
   MyClass1(MyFunction&& func): mFunc(std::move(func)) {}

 private:
   MyFunction mFunc;
};

class MyClass2 {
 public:
  MyClass1* getClass1(MyFunction&& func) {
    return new MyClass1(std::move(func));
  }
};

int main() {
  MyClass2 cl2;
  const auto& f = [] (int i) { return i; };

  MyClass1* cl1 = cl2.getClass1(f);
}

Live Example

【讨论】:

  • 'f' 看起来像一个左值。它如何与右值引用一起工作?
猜你喜欢
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 1970-01-01
  • 2010-09-10
相关资源
最近更新 更多