std::function 的目的是什么以及如何使用它?

问题描述 投票:0回答:3

我有必要使用

std::function
,但我不知道以下语法是什么意思。

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

使用

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

c++ c++11 lambda function-pointers std-function
3个回答
219
投票

std::function
是类型擦除对象。这意味着它删除了某些操作如何发生的细节,并为它们提供了统一的运行时接口。对于
std::function
,主要的 1 操作是复制/移动、销毁和使用
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
  }
};

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

完整的 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
  }
};

请注意,在 中,模板参数被添加到 lambda 中,上面没有介绍这一点。

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

1 另外,还存储了RTTI(typeid),并且包含了回传到原始类型的操作。


87
投票

让我们分开吧:

std::函数

这是一个不带参数、不返回值的函数的声明。如果函数返回

int
,它看起来像这样:

std::function<int()>

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

std::function<int(int)>

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

[]() { FNAME(); };

[]
部分称为捕获子句。您可以在此处放置 lambda 声明的本地变量,并且您希望这些变量在 lambda 函数本身中可用。这就是说“我不想捕获任何东西”。如果这是在类定义中并且您希望该类可供 lambda 使用,您可以这样做: [this]() { FNAME(); };

下一部分是传递给 lambda 的参数,
与常规函数完全相同

。如前所述,std::function<void()>是一个指向不带参数的方法的签名,因此它也是空的。


其余部分是 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


5
投票
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);

所以上面的用法是不正确的。
但是如果我们用“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 //... };

© www.soinside.com 2019 - 2024. All rights reserved.