【问题标题】:Usage and Syntax of std::functionstd::function 的用法和语法
【发布时间】:2013-12-19 15:09:39
【问题描述】:

我必须使用std::function,但我不知道下面的语法是什么意思。

std::function<void()> f_name = []() { FNAME(); };

使用std::function的目的是什么?是做一个函数的指针吗?

【问题讨论】:

  • 我认为这里的主要问题不是关于std::function,而是关于 lambdas。
  • “也许阅读一些文档有帮助?” ——我读了,没看懂。如果只有某个地方我可以寻求帮助...

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


【解决方案1】:

让我们分开:

std::函数

这是一个不带参数且不返回值的函数的声明。如果函数返回int,它看起来像这样:

std::function<int()>

同样,如果它也采用 int 参数:

std::function<int(int)>

我怀疑你的主要困惑是下一部分。

[]() { FNAME(); };

[] 部分称为捕获子句。在这里,您放置了 lambda 声明的本地变量,并且您希望在 lambda 函数本身可用。这就是说“我不希望任何东西被捕获”。如果这是在类定义中,并且您希望该类可用于 lambda,您可以这样做:

[this]() { FNAME(); };

下一部分是传递给 lambda 的参数,与普通函数完全相同。如前所述,std::function&lt;void()&gt; 是一个签名,指向一个不带参数的方法,所以这里也是空的。

剩下的部分就是 lambda 本身的主体,就好像它是一个普通函数一样,我们可以看到它只是调用了函数FNAME

另一个例子

假设您有以下签名,即可以将两个数字相加的东西。

std::function<int(int, int)> sumFunc;

我们现在可以这样声明一个 lambda:

sumFunc = [](int a, int b) { return a + b; };

不确定您是否使用 MSVC,但这里有一个指向 lamda 表达式语法的链接:

http://msdn.microsoft.com/en-us/library/dd293603.aspx

【讨论】:

  • [](int a, int b) { return a + b; 有什么不同? };和 [int a, int b]() { 返回 a + b; }; ???
  • @user2982229 手数。一个从本地范围捕获ab,另一个以ab 作为参数调用。
【解决方案2】:

std::function 是一个类型擦除对象。这意味着它删除了一些操作如何发生的细节,并为它们提供了一个统一的运行时接口。对于std::function,主要的1 操作是复制/移动、销毁和使用operator() 的“调用”——“类似于调用运算符的函数”。

用不太深奥的英语来说,这意味着std::function 可以包含几乎任何在你调用它时就像函数指针的对象。

它支持的签名放在尖括号内:std::function&lt;void()&gt; 接受零参数并且不返回任何内容。 std::function&lt; double( int, int ) &gt; 接受两个 int 参数并返回 double。一般来说,std::function 支持存储任何类函数对象,其参数可以从其参数列表转换,并且其返回值可以转换为它的返回值。

重要的是要知道std::function 和 lambdas 是不同的,如果兼容的话。

该行的下一部分是 lambda。这是 C++11 中的新语法,增加了编写简单的类函数对象的能力——可以使用() 调用的对象。此类对象可以被类型擦除并存储在 std::function 中,但会产生一些运行时开销。

[](){ code } 特别是一个非常简单的 lambda。对应的是:

struct some_anonymous_type {
  some_anonymous_type() {}
  void operator()const{
    code
  }
};

上述简单伪函数类型的实例。像上面这样的实际类是由编译器“发明”的,具有实现定义的唯一名称(通常包括用户定义类型不能包含的符号)(我不知道您是否有可能在不发明的情况下遵循标准这样一个类,但我所知道的每个编译器实际上都创建了这个类)。

完整的 lambda 语法如下所示:

[ capture_list ]( argument_list )
-> return_type optional_mutable
{
  code
}

但许多部分可以省略或留空。 capture_list 对应于生成的匿名类型及其成员变量的构造函数,argument_list 对应于operator() 的参数,返回类型对应于返回类型。当使用 capture_list 创建实例时,也会神奇地调用 lambda 实例的构造函数。

[ capture_list ]( argument_list ) -> return_type { code }

基本上变成了

struct some_anonymous_type {
  // capture_list turned into member variables
  some_anonymous_type( /* capture_list turned into arguments */ ):
    /* member variables initialized */
  {}
  return_type operator()( argument_list ) const {
    code
  }
};

请注意,在 中,模板参数被添加到 lambdas 中,上面没有提到。

[]<typename T>( std::vector<T> const& v ) { return v.size(); }

1另外存储RTTI(typeid),包括cast-back-to-original-type操作。

【讨论】:

  • 在不太深奥的英语中,人们不会使用“abstruse”这个词。我不得不查一下:wordreference.com/definition/abstruse。意思是“难以理解”。所以,深奥这个词是相当深奥的。
猜你喜欢
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
  • 2015-02-20
  • 2016-04-27
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多