C++11实用技术(二)std::function和bind绑定器

简介: C++11实用技术(二)std::function和bind绑定器


简介

C++11新增了std::function和std::bind。用于函数的包装以及参数的绑定。可以替代一些函数指针回调函数的场景。

std::function

std::function对象包装器

std::function是可调用对象的包装器,它可以用来用统一的方式来处理函数、函数对象、函数指针,并允许保存和延迟执行它们。比较难理解,可以从代码上深入:

#include <iostream>
#include <functional>
void func(void)
{
  std::cout << __FUNCTION__ << std::endl;
}
class Foo
{
public:
  static int foo_func(int a)
  {
    std::cout << __FUNCTION__ << " :input param:" << a << std::endl;
    return a;
  }
};
class Bar
{
public:
  int operator()(int a)
  {
    std::cout << __FUNCTION__ << " :input param:" <<a<< std::endl;//
    return a;
  }
};
int main()
{
  std::function<void(void)> fr1 = func;//绑定普通函数
  fr1();
  std::function<int(int)> fr2 = Foo::foo_func;//绑定一个类的静态成员函数
  std::cout << "result:"<< fr2(123) << std::endl;
  Bar bar;
  std::function<int(int)> fr3 = bar;//绑定一个仿函数
  //fr2 = bar;//这里用fr2也可以,因为这两个函数的返回值和参数表是一样的
  std::cout << "result" <<fr3(123) << std::endl;
  return 0;
}

注意:代码中__FUNCTION__是预定义标识符,基本功能是实现返回所在函数的名字,便于调试日志打印。

运行结果:

可以看出使用给std::function赋值上对应的函数返回值和函数参数表,它就可以容纳这一类调用方式的函数,被称为“函数包装器”。如上述的fr2可以容纳Foo::foo_func和bar。

这里可以看出function类似于函数指针的作用,可以保存各种类型的函数地址。

std::function做回调函数

#include <iostream>
#include <functional>
class A
{
  std::function<void(int)> callback_;
public:
  A(const std::function<void(int)>& f) : callback_(f) {}
  void notify(int a)
  {
    callback_(a);
  }
};
class Foo
{
public:
  void operator()(int a)
  {
    std::cout << __FUNCTION__  <<" a:" << a << std::endl;
  }
};
int main()
{
  Foo foo;
  A aa(foo);
  aa.notify(111);
  return 0;
}

这里可以看出function可以取代函数指针的作用,可以用function保存函数延迟执行,所有比较适合用在回调函数场景。

std::bind绑定器

std::bind可以将可调用对象和其参数一起绑定,绑定后的结果可以用std::function进行保存。

其中绑定普通函数和绑定成员函数的写法有所不同。

bind绑定普通函数

#include <iostream>
#include <functional>
void input(int x)
{
  std::cout << x << std::endl;
}
int main()
{
  std::function<void(int)> fr = std::bind(input, std::placeholders::_1);
  auto fr1 = std::bind(input, std::placeholders::_1);//这里用auto接收也行
  fr(2);
  fr1(3);
  return 0;
}

其中std::placeholders::_1是一个占位符,表示这个位置将在函数调用时,被传入的第一个参数替代。

占位符的使用方法

#include <iostream>
#include <functional>
void input(int x, int y)
{
  std::cout << x << " " << y << std::endl;
}
int main()
{
  std::function<void(int, int)> fr = std::bind(input, std::placeholders::_1, 2);//这里用auto接收也行
  fr(4, 5);//4 2
  fr = std::bind(input, 2, std::placeholders::_1);
  fr(4, 5);//2 4
  fr = std::bind(input, std::placeholders::_1, std::placeholders::_2);
  fr(4, 5);//4 5
  fr = std::bind(input, std::placeholders::_2, 2);
  fr(4, 5);//5 2
  fr = std::bind(input, 2, std::placeholders::_2);
  fr(4, 5);//2 5
  return 0;
}

结果:

在绑定参数时,可以通过占位符std::placeholders来决定空位参数会属于调用发生时的第几个参数。

bind绑定成员函数

bind可以绑定成员函数和成员变量。其中绑定成员函数和绑定普通函数时是有一些差别的。

#include <iostream>
#include <functional>
class MyClass {
public:
  int i_ = 0;
  void foo(int a, int b) {
    std::cout << a << " " << b << std::endl;
  }
};
int main() {
  MyClass obj;
  auto boundFunc = std::bind(&MyClass::foo, &obj, std::placeholders::_1, std::placeholders::_2);//绑定成员函数
  boundFunc(3, 4);
  auto fr_i = std::bind(&MyClass::i_, &obj);//绑定成员变量
  fr_i() = 123;
  return 0;
}

当使用 std::bind 绑定成员函数时,需要注意以下几点:

  • 需要使用成员函数的指针或函数对象来进行绑定。对于指针,需要使用 & 取址符号获取成员函数的地址。
  • 需要提供对象的指针(或引用)作为第一个参数,以便在调用时正确地调用成员函数。

可以看到绑定普通函数时是不需要提供对象的指针或引用作为参数。

目录
相关文章
|
5天前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
22 0
|
3月前
|
存储 算法 C++
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
文章详细探讨了C++中的泛型编程与STL技术,重点讲解了如何使用模板来创建通用的函数和类,以及模板在提高代码复用性和灵活性方面的作用。
58 2
C++提高篇:泛型编程和STL技术详解,探讨C++更深层的使用
|
2月前
|
C++
C++ 20新特性之结构化绑定
在C++ 20出现之前,当我们需要访问一个结构体或类的多个成员时,通常使用.或->操作符。对于复杂的数据结构,这种访问方式往往会显得冗长,也难以理解。C++ 20中引入的结构化绑定允许我们直接从一个聚合类型(比如:tuple、struct、class等)中提取出多个成员,并为它们分别命名。这一特性大大简化了对复杂数据结构的访问方式,使代码更加清晰、易读。
43 0
|
2月前
|
C++ 容器
函数对象包装器function和bind机制
函数对象包装器function和bind机制
22 0
|
3月前
|
安全 C++
C++: std::once_flag 和 std::call_once
`std::once_flag` 和 `std::call_once` 是 C++11 引入的同步原语,确保某个函数在多线程环境中仅执行一次。
|
4月前
|
人工智能 Anolis
聚焦C++20 最新标准!技术 Workshop 精彩亮点一览 | 2024 龙蜥大会
多场技术 Workshop、多位领域专家亲自授课,分享独家洞察与宝贵经验。
|
4月前
|
算法 C# 开发工具
《黑神话:悟空》背后的编程语言揭秘——超越C++的多元技术融合
【8月更文挑战第27天】在游戏开发领域,一款游戏的成功往往离不开其背后强大的技术支持和编程语言的精妙运用。《黑神话:悟空》作为备受瞩目的国产单机动作游戏,其开发过程不仅涉及了多种编程语言,更是一次技术创新的集中展现。然而,当我们深入探讨其开发语言时,会发现它并非仅依赖于单一的C++,而是融合了多种编程语言的优势,共同铸就了这款游戏的辉煌。
291 0
|
5月前
|
C++ 运维
开发与运维函数问题之使用std::function实现回调函数的示例如何解决
开发与运维函数问题之使用std::function实现回调函数的示例如何解决
41 7
|
5月前
|
存储 C++ 运维
开发与运维函数问题之使用C++标准库中的std::function来简化回调函数的使用如何解决
开发与运维函数问题之使用C++标准库中的std::function来简化回调函数的使用如何解决
55 6
|
5月前
|
C++ 运维
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
76 2

热门文章

最新文章

下一篇
DataWorks