std :: function的用法和语法

use*_*229 18 c++ function-pointers std-function

我有必要使用,std::function但我不知道std::function语法是什么意思.

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

Yak*_*ont 51

std::function是一种类型擦除对象.这意味着它会删除某些操作发生的细节,并为它们提供统一的运行时接口.因为std::function,操作是复制/移动和'调用' operator()- '函数类似于调用操作符'.

在较不深奥的英语中,它意味着std::function几乎可以包含任何对象,就像你调用它时的函数指针一样.

它支持的签名位于尖括号内:std::function<void()>取零参数并且不返回任何内容. std::function< double( int, int ) >接受两个int参数并返回double.通常,std::function支持存储任何类似函数的对象,其参数可以从其参数列表转换,并且其返回值可以转换为其返回值.

重要的是要知道std::function和lambda是不同的,如果兼容,野兽.

该行的下一部分是lambda.这是C++ 11中的新语法,用于添加编写简单函数类对象的能力 - 可以调用的对象().这些对象可以被类型擦除并std::function以一些运行时开销为代价存储.

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

struct some_anonymous_type {
  some_anonymous_type() {}
  void operator()const{
    code
  }
};
Run Code Online (Sandbox Code Playgroud)

上述简单伪函数类型的一个实例.像上面这样的实际类是由编译器"发明"的,实现定义了唯一的名称(通常包括没有用户定义类型可以包含的符号)(我不知道你是否可以遵循标准而不发明这样的类,但我知道的每个编译器实际上创建了类).

完整的lambda语法如下所示:

[ capture_list ]( argument_list )
-> return_type optional_mutable
{
  code
}
Run Code Online (Sandbox Code Playgroud)

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

[ capture_list ]( argument_list ) -> return_type { code }
Run Code Online (Sandbox Code Playgroud)

基本上变成了

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
  }
};
Run Code Online (Sandbox Code Playgroud)

  • 在不太深奥的英语中,人们不会使用“abstruse”这个词。我必须查一下:https://www.wordreference.com/definition/abstruse。意思是“难以理解”。所以,深奥这个词是相当深奥的。 (30认同)
  • 所以你说“深奥”是自逻辑的。 (2认同)

Moo*_*ice 24

让我们分开吧:

的std ::功能

这是一个不带参数的函数的声明,并且不返回任何值.如果函数返回了int,它将如下所示:

std::function<int()>
Run Code Online (Sandbox Code Playgroud)

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

std::function<int(int)>
Run Code Online (Sandbox Code Playgroud)

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

[]() { FNAME(); };
Run Code Online (Sandbox Code Playgroud)

[]部分称为捕获子句.在这里,您可以放置​​lambda声明的局部变量,并希望 lambda函数本身中可用.这就是说"我不想要任何东西被捕获".如果这是在类定义中并且您希望该类可用于lambda,则可以执行以下操作:

[this]() { FNAME(); };
Run Code Online (Sandbox Code Playgroud)

接下来的部分是传递给lambda的参数,与它是常规函数完全相同.如前所述,std::function<void()>签名指向不带参数的方法,因此也是空的.

其余部分是lambda本身的主体,好像它是一个常规函数,我们可以看到它只是调用函数FNAME.

另一个例子

假设您有以下签名,即可以将两个数字相加的内容.

std::function<int(int, int)> sumFunc;
Run Code Online (Sandbox Code Playgroud)

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

sumFunc = [](int a, int b) { return a + b; };
Run Code Online (Sandbox Code Playgroud)

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

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

  • @ user2982229很多.一个从本地范围捕获`a`和`b`,另一个用`a`和`b`作为参数调用. (3认同)
  • [](int a, int b) { return a + b; 之间有什么不同?}; 和 [int a, int b]() { return a + b; }; ??? (2认同)

小智 5

带有捕获的 lambda(有状态 lambda)不能互相分配,因为它们具有唯一的类型,即使它们看起来完全相同。为了能够通过捕获来存储和传递 lambda,我们可以使用“ std::function ”来保存由 lambda 表达式构造的函数对象。基本上,“ std::function ”是为了能够将具有不同内容结构的 lambda 函数分配给 lambda 函数对象。

经验:

auto func = [](int a){
 cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //ATTENTION(ERROR!): assigning a new structure to the same object
 cout << "x:" << x << ",a:" << a << endl;
};
func(2);
Run Code Online (Sandbox Code Playgroud)

所以上面的用法是不正确的。但是如果我们用“std::function”定义一个函数对象:

auto func = std::function<void(int)>{};
func = [](int a){
  cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //CORRECT. because of std::function
  //...
}; 

int y = 11;
func = [x,y](int a){ //CORRECT
 //...
}; 
Run Code Online (Sandbox Code Playgroud)