当前位置: 首页 > article >正文

C++可调用对象

C++11中有一个重要的概念,叫可调用对象,

可调用对象用途广泛,比如作为线程的执行对象,或者在使用一些基于范围的模版函数时( sort()、all_of()、find_if()),常常需要我们传入一个可调用对象,以指明我们需要对范围中的每个元素进行怎样的处理。

总的来说,可调用对象有以下几种,

  • 普通函数

  • 函数指针

  • 仿函数,即重载了operator()运算符的类对象

  • 匿名函数,即Lambda表达式

  • std::function

其中前面三种用法比较简单,放在一类中讲

普通函数、函数指针、仿函数

#include <iostream>
#include <thread>
#include <functional>
#include <algorithm>
#include <vector>

//仿函数
struct functor{
    int operator()(const int &a, const int &b) const{
        return a < b;
    }
};
//普通函数
bool normal_func_cmp(const int &a, const int &b) {
    return a < b; // 从小到大排列
}

//函数指针
typedef bool (*p_func)(const int &a, const int &b);
int main(int argc, const char * argv[]) {
    // insert code here...
	std::vector<int> v1 = {1, 5, 7, 4, 6, 2, 6};
	std::vector<int> v2 = v1;
	std::vector<int> v3 = v1;

	//使用普通函数排序
	sort(v1.begin(), v1.end(), normal_func_cmp);
	for(auto num : v1) {
	    std::cout << num << ' ';
	}
	std::cout << std::endl;

	//使用仿函数排序
	sort(v2.begin(), v2.end(), functor());
	for(auto num : v2) {
	    std::cout << num << ' ';
	}
	std::cout << std::endl;

	//使用函数指针排序
	p_func p = normal_func_cmp;
	sort(v3.begin(), v3.end(), p);
	for(auto num : v3) {
	    std::cout << num << ' ';
	}
	return 0;
}

匿名函数 Lambda 表达式

定义

[captures] (params) mutable -> return_type { statments;}

  • [captures]为捕获列表,用于捕获外层变量。[&]表示捕获当前范围内所有局部变量。

    • [val]:表示以传值方式捕捉变量val

    • [=]:表示以传值方式捕捉当前作用域中的变量,包括this指针。

    • [&val]:表示以引用方式传递捕捉变量val。

    • [&]:表示以引用方式传递捕捉当前作用域中的所有变量,包括this指针。

    • [this]:表示以传值方式捕捉当前的this指针。

  • params:参数列表。与普通函数参数列表使用相同。如果不需要传递参数,可以连同()一起省略。

  • mutable : 默认情况下,lambda函数总是一个const函数,捕捉的传值参数具有常性,mutable可以取消常性。使用mutable修饰符时,参数列表不能省略,即使参数为空。

  • ->return_type : 返回值,如果没有返回类型,则可以省略这部分。想知道为什么返回类型可以这么表示,这涉及到c++11的另一特性,参见自动类型推导。

  • statments: {函数体}:在函数体内除了可以使用参数外,还能使用捕捉的变量。

举例

void lambda_test() {
		/* 最简单的lambda表达式 */
    []{};
		//值传递
		int a = 1;
		int b = 2;
		auto add_lambda_func_val = [=] () mutable{ a = a + b;};
		add_lambda_func_val();
		//由于传递的是当前局部变量的拷贝,所以a不会被修改
		std::cout << a << " " << b << std::endl;
		
		//引用传递
		auto add_lambda_func_ref = [&] (){  a = a + b;};
		add_lambda_func_ref();
		//由于传递的是当前局部变量的引用,所以a被修改
		std::cout << a << " " << b << std::endl;
		
		//可以对单个变量进行捕捉
		auto add_lambda_func_ref2 = [&a,b] () mutable { a = a + b; b = a + b; };
		add_lambda_func_ref2();
		std::cout << a << " " << b << std::endl;
} 

std::function

std::function在C++11后加入标准,可以用它来描述C++中所有可调用实体,它是是可调用对象的包装器,声明如下:

普通声明

#include <functional>
// 声明一个返回值为int,参数为两个int的可调用对象类型
std::function<int(int, int)> Func;

其他函数实体转化为std::function

std::function 的强大之处在于,它能兼容所有callable实体

 //所有callable实体都能给function接收,这里以lambda为例
  auto lambda = [](int a, int b)->int {return a + b;};
  test_functionnal = lambda;
...
//成员函数和静态函数比较特殊
//成员函数需要传入对象指针
//std::placeholders::_1是占位符,代表需要接收一个参数,如果要接收多个,可以使用std::placeholders::_2、std::placeholders::_3...

    MyClass object;
    test_functionnal = std::bind(&MyClass::sum, &object, std::placeholders::_1, std::placeholders::_2);
    std::cout << "class member function : "<< test_functionnal(1, 2)<< std::endl;

http://www.kler.cn/a/286324.html

相关文章:

  • 神经网络——CIFAR10小实战
  • 如何构建大型超市数据处理系统?Java SpringBoot搭配MySQL,实现高效数据管理!
  • Axure RP10安装教程(Pro版)
  • 考试评分系统设计与实现/基于django的在线考试系统
  • 发布npm包到GitLab教程
  • 人工智能和机器学习5 (复旦大学计算机科学与技术实践工作站)语言模型相关的技术和应用、通过OpenAI库,调用千问大模型,并进行反复询问等功能加强
  • 【网络安全】服务基础第一阶段——第四节:Windows系统管理基础---- NTFS安全权限与SMB文件共享服务器
  • Android游戏开发常见知识合集(Unity3D)
  • 距离向视数(Range Looks)方位向视数(Azimuth Looks)
  • MLM之Qwen:Qwen2-VL的简介、安装和使用方法、案例应用之详细攻略
  • 比较一下React与Vue
  • 《机器学习》—— K-means 聚类算法
  • 【微处理器系统原理与应用设计】微处理器的基本架构之组成原理和系统结构
  • 解决Qt报“undefined reference to vtable for“错误
  • 科技改变搜索习惯:Anytxt Searcher,重新定义你的信息获取方式!
  • 【王树森】Transformer模型(2/2): 从Attention层到Transformer网络(个人向笔记)
  • Java智慧社区全能平台集成跑腿家政及本地生活服务商城系统小程序源码
  • MySQL事务处理详解:实现数据一致性与隔离性的艺术
  • 【分层强化学习】Option Critic 的 CartPole-v1 的简单实例
  • MATLAB 地面点构建三角网(83)