c++ 类在构造函数中使用 lambda

Posted

技术标签:

【中文标题】c++ 类在构造函数中使用 lambda【英文标题】:c++ class using a lambda in constructor 【发布时间】:2020-06-30 16:41:17 【问题描述】:

使用 c++11 我想创建一个使用 lambda 作为计算一部分的类。

//contrived sample of potential usage
void random_class::some_function(void)

 auto an_object = new my_custom_object(5, [this]() return random_class_member * 5; );
 an_object.do_some_processing();
 random_class_member++;
 an_object.do_some_processing();

我不太确定如何声明和定义 my_custom_object。

class my_custom_object

public:
 template <typename Proc>
 my_custom_object(int a, Proc p)
 
  privatea = a;
  privatep = p;
 
 void do_some_processing()
 
  privatea += privatep();
 
private:
 int privatea;
 Proc privatep;

未知类型名称'Proc'

【问题讨论】:

它们之间没有关系 您可能需要查看 std::function 来存储 lambda。 你需要template整个类,而不仅仅是构造函数 如果整个类都是模板化的,我将如何使用带有 lambda 的 my_custom_object? random_class::some_function 会是什么样子? 为什么是privatea = a?为什么不this.a = a?或my_custom_object(int a, std::function&lt;int(void)&gt; p) : a(a), p(p) 【参考方案1】:

您可以采取两种方法。

使用类型擦除的std::function

例如:

class my_custom_object 
public:
    my_custom_object(int a, std::function<void()> p)
    
        privatea = a;
        privatep = p;
    
    void do_some_processing()
    
        privatea += privatep();
    

private:
    int privatea;
    std::function<void()> privatep;
;

这允许my_custom_object 接受任何不接受参数的类似函数的东西。但是有一些性能开销,因为对privatep 的调用必须在运行时解决。这可能可以忽略不计,但如果这发生在程序的性能关键部分的紧密循环中,则可能很重要。

呼叫站点看起来与您现在的完全一样:

void random_class::some_function(void)

   my_custom_object an_object5, [this]() return random_class_member * 5; ;
   an_object.do_some_processing();
   random_class_member++;
   an_object.do_some_processing();

模板 my_custom_object 它所拥有的函数类型。

例如:

template <typename Proc>
class my_custom_object 
public:
    my_custom_object(int a, Proc p)
    
        privatea = a;
        privatep = p;
    
    void do_some_processing()
    
        privatea += privatep();
    

private:
    int privatea;
    Proc privatep;
;

这将允许您对privatep 的调用在编译时静态解析,这可能比使用std::function 的性能稍好。这确实意味着 Proc 的类型现在是 my_custom_object 类型的一部分,因此在某些情况下它的灵活性稍差。

由于 C++17 添加了类模板参数推导,调用站点看起来完全一样:

void random_class::some_function(void)

   my_custom_object an_object5, [this]() return random_class_member * 5; ;
   an_object.do_some_processing();
   random_class_member++;
   an_object.do_some_processing();

如果您必须使用 C++17 之前的编译器,则必须将模板参数显式指定为 my_custom_object

void random_class::some_function(void)

   auto func = [this]() return random_class_member * 5; ;
   my_custom_object<decltype(func)> an_object5, func;
   an_object.do_some_processing();
   random_class_member++;
   an_object.do_some_processing();

【讨论】:

【参考方案2】:

如果 lambda 的签名是固定的,您可以删除模板并使用 std::function&lt;ReturnType(parameters)&gt;。你的情况

using Proc = std::function<int(void)>;

应该可以。然后你可以传递一个不带参数并返回一个 int 的 lambda。

【讨论】:

以上是关于c++ 类在构造函数中使用 lambda的主要内容,如果未能解决你的问题,请参考以下文章

C++:对象和类|| 类的构造函数与析构函数

c++ 如何在构造函数中启动一个线程,从命名管道读取数据?

c++之构造函数,析构函数(五千字长文详解!)

[ C++ ] C++类与对象之 类中6个默认成员函数

为啥 C++ 映射类型参数在使用 [] 时需要一个空的构造函数?

c++派生类构造顺序