std :: bind和std :: function问题

时间:2011-11-10 16:18:15

标签: c++ c++11

int func(int x){return x;}
...
std::function<int(int)> x = std::bind(func, std::placeholders::_1);
x(123);
  1. x(123)是否实际调用operator()生成的仿函数的std::function,而operator()依次调用最终调用的std::bind生成的仿函数func func(123)?这是否被优化为与调用std::bind一样最优的东西?
  2. std::bind生成的仿函数在哪里生活?在什么范围? std::bind如何命名呢? (可以有名称冲突)
  3. lambda可以取代std::bind的所有用途吗?
  4. std::function最适合将其作为lambda实现吗?
  5. {{1}}的模板参数的语法是什么?如何解析它以及如何在其他地方使用该模板参数语法?

3 个答案:

答案 0 :(得分:16)

  

x(123)实际上是否调用了生成std :: function的仿函数的operator(),而该函数又调用了最终调用func的std :: bind生成的仿函数的operator()?这是否被优化为调用func(123)最优的东西?

我不会将operator() std::function描述为'生成'(它是常规成员),但除此之外这是一个很好的描述。优化取决于您的编译器,但要注意优化std::function的间接(需要使用类型擦除),编译器可能需要执行英雄。

  

std :: bind生成的函子在哪里?在什么范围? std :: bind如何命名呢? (可以有名称冲突)

std::bind的调用返回一个未指定类型的仿函数,该仿函数的副本存储在x对象中。此副本将与x本身一样长。没有名字涉及,所以我不确定你的意思。

  

lambdas可以替换std :: bind的所有用法吗?

没有。考虑auto bound = std::bind(functor, _1);其中functor是一个带有重载operator()的类型,比如说longint。然后bound(0L)bound(0)的效果不同,你不能用lambda复制它。

  

将std :: bind作为最佳实现,而不是将其作为lambda实现吗?

这取决于编译器。衡量自己。

  

std :: function的模板参数的语法是什么?如何解析它以及如何在其他地方使用该模板参数语法?

这是一种功能类型。也许您已经熟悉指针/函数引用的语法:void(*)()int(&)(double)。然后只需删除类型中的指针/引用,您只需要一个函数类型:void()int(double)。您可以使用以下内容:

typedef int* function_type(long);
function_type* p; // pointer to function

答案 1 :(得分:6)

  

1。 x(123)是否实际调用了operator()生成的仿函数的std::function,而仿函数又调用了仿函数的operator()生成std::bind,最终调用func?这是否被优化为与调用func(123)一样最优的东西?

如果您启用了优化功能,则“内容”会被内联,您可以指望这与调用func(123)一样最佳。

  

2。 std::bind生成的仿函数在哪里?在什么范围? std::bind如何命名呢? (可以有名称冲突)

精确:bind生成一个“转瞬即逝”的实现定义绑定表达式,可分配给function<>。功能只是一个类模板(谢谢,Luc T.)。它存在于标准库中。但是,绑定表达式是实现定义的。

标准库 带有特征(std::is_bind_expression<>)以允许MPL检测此类表达式。绑定表达式在std :: function上的一个决定性特征是它们(我称之为)延迟可调用对象(即它们保留完整的调用站点语义,包括在实际中选择重载的能力申请网站)。另一方面,std::function<>提交单个原型并在内部存储callable object类型擦除( think variantany )。

  

3. Lambda可以替换std :: bind的所有用法吗?

     

4。 std :: bind是最佳实现,而不是将其作为lambda实现吗?

AFAICT lambdas应该编译为与绑定表达式大致相同。我认为 lambdas无法做到的一件事就是可以 nested bind expressions 编辑虽然嵌套绑定表达式的特定习惯用法不能使用lambdas复制,但lambdas当然能够更自然地表达(几乎)相同的内容:

 bind(f, bind(g, _1))(x); 
 // vs.
 [](int x) { f(g(x)); };

  

5. std::function的模板参数的语法是什么?如何解析它以及如何在其他地方使用该模板参数语法?

它只是一个函数签名(函数的 type ),作为模板参数传递。

您也可以将它用作函数参数类型,降级到函数指针(类似于数组按值参数降级为指针的方式,感谢David!)。 在实践中,大多数地方,只要您不需要名称变量/类型:

 void receiveFunction(void(int, double)); // spunky 'function<>'-style syntax

 void sample(int, double) { } 

 int main()
 { 
     receiveFunction(sample);
 }

 void receiveFunction(void (*f)(int, double)) // boring 'old' style syntax
 //                   void ( f)(int, double)  // ... also ok
 {
     // ..
 }

答案 2 :(得分:0)

  

lambdas可以替换std :: bind的所有用法吗?

C ++ 14将允许lambdas主要替换bind。特别回应Luc Danton的答案,在C ++ 14中,你可以使用auto编写模板化的lambda,使bound(0)bound(0L)的行为不同。