当前位置: 首页 > 编程日记 > 正文

【C++】多线程与并发【一】

文章目录

      • part 0:多线程简介
      • part 1:多线程构造
        • 它用于构造线程对象。
        • 参量
      • part 2:多线程析构
        • 它破坏线程对象。
      • part 3:多线程operator=
        • 参量 Parameters
        • 返回值
    • Data races
      • part 4:joinable 它返回线程ive对象是否可连接,则返回true,否则返回false。 表示的是否可连接状态.
      • part 5:多线程std :: thread :: get_id
        • Declaration
      • C++11
      • part 6:native_handle 返回底层实现定义的线程句柄
      • part 7:hardware_concurrency 返回实现支持的并发线程数
        • Description
        • Return Value
      • part 8:join 线程执行完成后返回
      • part 9:detach 容许线程从线程句柄独立开来执行
        • Description
      • part 10:swap 交换二个 `thread` 对象
        • Description
        • Declaration
      • part 11:std::swap 特化 [std::swap](https://zh.cppreference.com/w/cpp/algorithm/swap) 算法
        • Description
        • Declaration
        • Parameters
        • 实例:
    • 小结:
        • **当线程不需要相互依赖,不会产生数据竞争,或不是流水的实现思路下,用detach();**
        • **当可能产生数据竞争,数据之间相互依赖,算法实现设计为流水的情况下,使用join()函数,使其他线程进入阻塞状态。**

part 0:多线程简介

Thread是一个指令序列,它可以在多线程环境中与其他这样的序列同时执行,同时共享同一个地址空间。

Thread is a sequence of instructions that can be executed concurrently with other such sequences in multithreading environments, while sharing a same address spac.

Member typesDescription成员类型
idIt is a values of this type are returned by thread::get_id and this_thread::get_id to identify threads.It is a thread id.表示线程的id1
native_handle_typeIt is a member type and it presents in class thread if the library implementation supports it.实现定义It is a native handle type.2
Member functions成员函数
constructorIt is used to construct thread.构造新的 thread 对象3
destructorIt is used to destructor thread.析构 thread 对象,必须合并或分离底层线程4
operator=It is a move-assign thread.移动 thread 对象5
get_idIt is used to get thread id.返回线程的 *id6
joinableIt is used to check if joinable.检查线程是否可合并,即潜在地运行于平行环境中7
joinIt is used to join thread.等待线程完成其执行8
detachIt is used to detach thread.容许线程从线程句柄独立开来执行9
swapIt is used to swap threads.交换二个 thread 对象10
native_handleIt is used to get native handle.返回底层实现定义的线程句柄11
hardware_concurrencyIt is used to detect hardware concurrency.返回实现支持的并发线程数12
Non-member overload & description非成员函数
swapIt is used to swap threads.特化 std::swap 算法13

在这里插入图片描述

part 1:多线程构造

它用于构造线程对象。

It is used to constructs a thread object.

以下是std :: thread :: thread函数的声明。

thread() noexcept;
template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);
thread (const thread&) = delete;	
thread (thread&& x) noexcept;

参量

  • **fn-**它是函数的指针,成员的指针或任何可移动构造的函数对象。
  • **args …-**传递给fn调用的参数。
  • **x-**这是一个线程对象。
#include <thread> //头文件
#include <iostream>
using namespace std;void fn1(void)
{cout << "fn1" << endl;
}void fn2(int a)
{cout << "fn2 " << a << endl;
}void fn3(int& a)
{cout << "fn3 " << a << endl;
}class cls
{
public:void fn1(int a){cout << "cls::fn1" << endl;}
};void test01() {std::thread t1(&fn1); //线程对象构造后,即开始执行//可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detachedt1.join(); //必须执行join,不然运行期错误std::thread t2(&fn2, 2); //传入函数参数t2.join();int n = 2;std::thread t3(&fn3, std::ref(n)); //传入引用参数t3.join();cls c;//线程入口为类成员函数std::thread t4(&cls::fn1, &c, 2);t4.join();
}
int main()
{test01();getchar();return 0;
}

img

cpp多线程并发 头文件的使用,正则化实现

#include <iostream>
#include <thread>int main(void)
{std::thread x([]()->void {int i = 4;while (i--){std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "*" << std::endl;}return;});std::thread y([]()->void {int i = 4;while (i--){std::this_thread::sleep_for(std::chrono::seconds(5));std::cout << "-" << std::endl;}return;});std::cout << std::thread::hardware_concurrency() << std::endl; //检测计算机并发数std::cout << "x.hand " << x.native_handle() << std::endl;std::cout << "y.hand " << y.native_handle() << std::endl;//脱离主线程后不能直接获取句柄,所以放输出语句后面后面x.detach();y.detach();std::this_thread::sleep_for(std::chrono::seconds(30));//等待程序执行完成return 0;
}

img

part 2:多线程析构

它破坏线程对象。

It destroys the thread object. Following is the declaration for std::thread::~thread function.

~thread();

part 3:多线程operator=

以下是std :: thread :: operator =函数的声明。

It is used to move-assign thread. Following is the declaration for std::thread::operator= function.

thread& operator= (thread&& rhs) noexcept;	
thread& operator= (const thread&) = delete;

参量 Parameters

rhs − It is a othread object.

RHS -这是一个othread对象。

返回值

它返回* this

Data races

rhs和对象均被修改。

Both rhs and the object are modified.

part 4:joinable 它返回线程ive对象是否可连接,则返回true,否则返回false。 表示的是否可连接状态.

It returns whether the thread object is joinable.

It returns true if the thread is joinable or else false.

#include <iostream>
#include <thread>void foo02() {std::this_thread::sleep_for(std::chrono::seconds(2));
}void test02() {//joinablestd::thread t2;//创建了线程对象std::cout << "before joneable: " << t2.joinable() << std::endl;t2 = std::thread(foo02);//joinable  //实例化std::thread对象时传递了“函数名/可调用对象”std::cout << "after joneable: " << t2.joinable() << std::endl;t2.join();//等待std::cout << "after joining,joinable: " << t2.joinable()<<std::endl;
}int main() {	test02();getchar();return 0;
}

part 5:多线程std :: thread :: get_id

Declaration

下面是std::thread::get_id函数的声明。 Following is the declaration for std::thread::get_id function.

id get_id() const noexcept;

C++11

id get_id() const noexcept;

Return Value:It returns the thread id.

Exceptions:No-throw guarantee − never throws exceptions.

Data races:he object is accessed.

#include <iostream>
#include <thread>
#include <chrono>void foo() {std::this_thread::sleep_for(std::chrono::seconds(1));
}int main() {std::thread sample(foo);std::thread::id sample_id = sample.get_id();std::thread sample2(foo);std::thread::id sample2_id = sample2.get_id();std::cout << "sample's id: " << sample_id << '\n';std::cout << "sample2's id: " << sample2_id << '\n';sample.join();sample2.join();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RgA6jWST-1609517496473)(C:\Users\guoqi\AppData\Roaming\Typora\typora-user-images\1609344040208.png)]

part 6:native_handle 返回底层实现定义的线程句柄

Declaration:Following is the declaration for std::thread::native_handle function.

native_handle_type native_handle();

Return Value:It returns a value of member type thread::native_handle_type.

part 7:hardware_concurrency 返回实现支持的并发线程数

Description

It returns the number of hardware thread contexts.

static unsigned hardware_concurrency() noexcept;

Return Value

It returns the number of hardware thread contexts.

part 8:join 线程执行完成后返回

It returns when the thread execution has completed.

void foo03() {std::this_thread::sleep_for(std::chrono::seconds(2));
}
void bar03() {std::this_thread::sleep_for(std::chrono::seconds(2));
}
void test03() {//join 线程执行完成后返回//It returns when the thread execution has completed.std::cout << " starting helping ...." << std::endl;std::thread helper3(foo02);std::cout << " starting another helping ...." << std::endl;std::thread helper3_2(bar03);std::cout << " waiting for helpers finish...." << std::endl;helper3.join();//线程执行完成后返回helper3_2.join();std::cout << "  done!" << std::endl;
}int main() {test03();getchar();return 0;
}

part 9:detach 容许线程从线程句柄独立开来执行

Description

It returns when the thread execution has completed.

#include <iostream>
#include <chrono>
#include <thread>void independentThread() {std::cout << "Starting thread.\n";std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Exiting previous thread.\n";
}void threadCaller() {std::cout << "Starting thread caller.\n";std::thread t(independentThread);t.detach();std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Exiting thread caller.\n";
}int main() {threadCaller();std::this_thread::sleep_for(std::chrono::seconds(5));
}

part 10:swap 交换二个 thread 对象

Description

It swaps the state of the object with that of x.

Declaration

Following is the declaration for std::thread::swap function.

void swap (thread& x) noexcept;

part 11:std::swap 特化 std::swap 算法

Description

It is used to exchanges the state of the thread objects x and y.

Declaration

Following is the declaration for std::thread::swap function.

void swap (thread& x, thread& y) noexcept;

Parameters

x,y − It is a thread objects.

实例:

//thread1.cpp  创建线程,并观察线程的并发执行与阻塞等待#include <iostream>
#include <thread>
#include <chrono>using namespace std;void thread_function(int n)
{std::thread::id this_id = std::this_thread::get_id();			//获取线程IDfor(int i = 0; i < 5; i++){    cout << "Child function thread " << this_id<< " running : " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(n));   	//进程睡眠n秒}
}class Thread_functor
{
public:// functor行为类似函数,C++中的仿函数是通过在类中重载()运算符实现,使你可以像使用函数一样来创建类的对象void operator()(int n){std::thread::id this_id = std::this_thread::get_id();for(int i = 0; i < 5; i++){cout << "Child functor thread " << this_id << " running: " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(n));   //进程睡眠n秒}}	
};int main()
{thread mythread1(thread_function, 1);      // 传递初始函数作为线程的参数if(mythread1.joinable()) //判断是否可以成功使用join()或者detach(),返回true则可以,false则不可mythread1.join();                     // 使用join()函数阻塞主线程直至子线程执行完毕Thread_functor thread_functor;			 //函数对象实例化一个对象thread mythread2(thread_functor, 3);     // 传递初始函数作为线程的参数if(mythread2.joinable())mythread2.detach();  // 使用detach()函数让子线程和主线程并行运行,主线程也不再等待子线程//lambda表达式格式:[capture list] (params list) mutable exception-> return type { function body }auto thread_lambda = [](int n){			std::thread::id this_id = std::this_thread::get_id();for(int i = 0; i < 5; i++){cout << "Child lambda thread " << this_id << " running: " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(n));   //进程睡眠n秒}       };thread mythread3(thread_lambda, 4);     // 传递初始函数作为线程的参数if(mythread3.joinable())mythread3.join();                     // 使用join()函数阻塞主线程直至子线程执行完毕std::thread::id this_id = std::this_thread::get_id();for(int i = 0; i < 5; i++){cout << "Main thread " << this_id << " running: " << i+1 << endl;std::this_thread::sleep_for(std::chrono::seconds(1));}getchar();return 0;
}

线程创建的参数是函数对象,函数对象不止是函数指针成员函数指针,同时还包括函数对象(仿函数)lambda表达式。上面的代码分别用三种函数对象创建了三个线程**,其中第一个线程mythread1阻塞等待其执行完后继续往下执行**,第二个线程mythread2不阻塞等待在后台与后面的第三个线程mythread3并发执行,第三个线程继续阻塞等待其完成后再继续往下执行主线程任务。

为了便于观察并发过程,对三个线程均用了睡眠延时this_thread::sleep_for(duration)函数,且延时时间作为参数传递给该函数。这里的参数是支持C++泛型模板的,STL标准容器类型(比如Array/Vector/Deque/List/Set/Map/String等)都可以作为参数传递,但这里的参数默认是以拷贝的方式传递参数的,当期望传入一个引用时,要使用std::ref进行转换,实例见part 1中实例。
在这里插入图片描述
如果想要线程mythread2独立运行,修改如下

mythread2.detach(); ---》   mythread2.join();

在这里插入图片描述
线程mythread2和线程mythread3与主线程main 同步运行

mythread2.detach(); ---》   mythread2.join();
mythread3.join();   ---》   mythread3.detach();

在这里插入图片描述

小结:

当线程不需要相互依赖,不会产生数据竞争,或不是流水的实现思路下,用detach();

当可能产生数据竞争,数据之间相互依赖,算法实现设计为流水的情况下,使用join()函数,使其他线程进入阻塞状态。

针对任何线程(包括主线程),< thread > 还声明了一个命名空间std::this_thread,用以提高线程专属的全局函数。函数声明和效果见下表。 上面的代码就是利用了std::this_thread提供的函数获得当前线程的ID,让当前线程睡眠一段时间(一般需要< chrono >头文件提供duration或timepoint)的功能 。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-slwclSiT-1609517496481)(C:\Users\guoqi\AppData\Roaming\Typora\typora-user-images\1609503539479.png)]

参考资料:
https://zh.cppreference.com/w/cpp/thread/thread
https://www.tutorialspoint.com/cpp_standard_library
https://blog.csdn.net/m0_37621078/article/details/104909834

相关文章:

鼠标按键获取感兴趣区域

#include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> #include <stdio.h> using namespace cv; using namespace std; // 全局变量图像源 cv::Mat srcImage; // 所选矩形区域 cv::Rect roiRect; …

git在不同操作系统下自动替换换行符

2019独角兽企业重金招聘Python工程师标准>>> 一天使用docker创建一个镜像执行报一个错 standard_init_linux.go:175: exec user process caused "no such file or directory"参考资料 http://blog.jobbole.com/46200/ http://neue.v2ex.com/t/309469 git …

关于jsp和eclipse服务器端的相关配置和JS的区别

今天配置了一番eclipse的服务器端&#xff0c;由此重新认识了web技术的皮毛&#xff1b; 话不多说&#xff0c;让我们开始&#xff1a; 一&#xff1a; 首先让我们了解一下js和jsp的技术之间的差别&#xff1a; 1&#xff09;js&#xff1a;https://zh.wikipedia.org/wiki/Java…

【C++】多线程与互斥锁【二】

文章目录1. 并发是什么1.1 并发与并行1.2 硬件并发与任务切换1.3 多线程并发与多进程并发2. 为什么使用并发2.1 为什么使用并发2.2 并发和多线程3. 并发需要注意的问题3.1 多线程中的数据竞争实例1&#xff1a;3.2 如何处理数据竞争&#xff1f;实例2&#xff1a;实例3&#xf…

用hosting.json配置ASP.NET Core站点的Hosting环境

通常我们在 Prgram.cs 中使用硬编码的方式配置 ASP.NET Core 站点的 Hosting 环境&#xff0c;最常用的就是 .UseUrls() 。 public class Program {public static void Main(string[] args){var host new WebHostBuilder().UseUrls("http://*:5000").UseKestrel().U…

鼠标按键获取感兴趣区域 2

#include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> #include <stdio.h> using namespace cv; using namespace std; // 全局变量图像源 cv::Mat srcImage; // 所选矩形区域 cv::Rect roiRect; …

偷看日历?9款 APP 涉嫌过度获取权限

最近网友已经看累了APP搞事的瓜&#xff0c;3月29日&#xff0c;“9款 APP 涉嫌过度获取权限”又上了热搜。 不久前上海消保委针对网购平台、旅游出行、生活服务等39款手机APP进行了涉及个人信息权限的评测&#xff0c;主要包括四个方面&#xff1a;App所使用的目标API级别、A…

【C++】多线程与条件变量【三】

文章目录1 条件变量是什么&#xff1f;实例1&#xff1a;2 条件变量本质&#xff1f;3 引入条件变量的原因&#xff1f;实例2&#xff1a;实例3&#xff1a;实例4&#xff1a;4 如何使用条件变量&#xff1f;4.1 std::condition_variable实例5&#xff1a;4.2 std::condition_v…

图像遍历反色处理,遍历多通道图片

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> using namespace cv; // 下标M.at<float>(i,j) 方法1-1 cv::Mat inverseColor1(cv::Mat srcImage) {cv::Mat tempImage srcImage.clone();int row t…

【Treap】bzoj1588-HNOI2002营业额统计

一、题目 Description 营业额统计 Tiger最近被公司升任为营业部经理&#xff0c;他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本&#xff0c;账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节…

推荐一款 Flutter Push 推送功能插件

又到了推荐好插件的时候了。开发 APP 避免不了使用「推送」功能。比如&#xff0c;新上架一个商品&#xff0c;或者最新的一条体育新闻&#xff0c;实时推送给用户。 比较了几家推送平台&#xff0c;貌似「极光」出了 Flutter 插件&#xff0c;所以就拿它试试手&#xff0c;顺便…

【C++】多线程与异步编程【四】

文章目录【C】多线程与异步编程【四】0.三问1.什么是异步编程&#xff1f;1.1同步与异步1.2 **阻塞与非阻塞**2、如何使用异步编程2.1 使用全局变量与条件变量传递结果实例1&#xff1a;2.2 使用promise与future传递结果实例2实例32.3使用packaged_task与future传递结果实例42.…

[LintCode] Maximum Subarray 最大子数组

Given an array of integers, find a contiguous subarray which has the largest sum. Notice The subarray should contain at least one number. Have you met this question in a real interview? YesExample Given the array [−2,2,−3,4,−1,2,1,−5,3], the contiguo…

图像补运算:反色处理

cv::Mat inverseColor1(cv::Mat srcImage) {cv::Mat tempImage srcImage.clone();int row tempImage.rows;int col tempImage.cols;// 对各个像素点遍历进行取反for (int i 0; i < row; i){for (int j 0; j < col; j){// 分别对各个通道进行反色处理tempImage.at<…

2018-2019-2 网络对抗技术 20165239Exp3 免杀原理与实践

2018-2019-2 网络对抗技术 20165239 Exp3 免杀原理与实践 win10 ip地址 192.168.18.1 fenix ip地址为 192.168.18.128 &#xff08;1&#xff09;杀软是如何检测出恶意代码的&#xff1f; •根据计算机病毒课程知道了每个病毒都有其对应的特征码&#xff0c;杀软是根据这些特征…

【C++】多线程与原子操作和无锁编程【五】

【C】多线程与原子操作和无锁编程【五】 1、何为原子操作 前面介绍了多线程间是通过互斥锁与条件变量来保证共享数据的同步的&#xff0c;互斥锁主要是针对过程加锁来实现对共享资源的排他性访问。很多时候&#xff0c;对共享资源的访问主要是对某一数据结构的读写操作&#…

jquery中ajax的dataType属性包括哪几项

参考ajax api文档&#xff1a;http://www.w3school.com.cn/jquery/ajax_ajax.asp dataType类型&#xff1a;String预期服务器返回的数据类型。如果不指定&#xff0c;jQuery 将自动根据 HTTP 包 MIME 信息来智能判断&#xff0c;比如 XML MIME 类型就被识别为 XML。在 1.4 中&a…

图像补运算:ptr反色处理

cv::Mat inverseColor3(cv::Mat srcImage) {cv::Mat tempImage srcImage.clone();int row tempImage.rows;// 将3通道转换为单通道int nStep tempImage.cols * tempImage.channels();for(int i 0; i < row; i) {// 取源图像的指针const uchar* pSrcData srcImage.ptr&l…

Android 在运行时请求权限

2019独角兽企业重金招聘Python工程师标准>>> 从 Android 6.0&#xff08;API 级别 23&#xff09;开始&#xff0c;用户开始在应用运行时向其授予权限&#xff0c;而不是在应用安装时授予。此方法可以简化应用安装过程&#xff0c;因为用户在安装或更新应用时不需要…

Markdown解决图片存储问题

文章目录Markdown1.前言2.图片引用方式方式1&#xff1a;可以任意比例放缩图片方式2&#xff1a;原比例引用图片3.推荐公式编辑器4.此外简单介绍下Markdown的一种轻量化工具Typora的使用方法。Markdown 1.前言 相信大家在使用Typora&#xff0c;经常会遇到图片编辑的问题&…

jenkins添加git源码目录时报Error performing command错误

简介 这是我在构建一个自动化部署项目中遇到的一个异常 解决步骤&#xff1a; 1、进入的jenkins的home目录&#xff0c;执行下面命令生成公钥和私钥 [rootjacky .jenkins]# ssh-keygen -t dsa 2、查看生成的公钥 [rootjacky .ssh]# cat /root/.ssh/id_dsa.pub ssh-dss AAAAB3Nz…

图像补运算:MatIterator_迭代器反色处理

#include <opencv2/opencv.hpp>#include <opencv2/video/background_segm.hpp>// 注意srcImage为3通道的彩色图片 cv::Mat inverseColor4(cv::Mat &srcImage) {cv::Mat tempImage srcImage.clone();// 初始化源图像迭代器 cv::MatConstIterator_<cv::Vec3…

浅谈同一家公司多个系统,共用登录用户名和密码

主要解决系统使用的加密方式不一致的问题&#xff0c; 比如几年前的系统A&#xff0c; 某某牵头无中生有的系统B 原先A用的php语言开发&#xff0c;比如叫做tap&#xff0c;是国外用来做项目管理的一款BS平台&#xff0c;&#xff08;和国内发禅道类似&#xff0c;省略***&…

Eigen/Matlab 使用小结

文章目录[Eigen Matlab使用小结](https://www.cnblogs.com/rainbow70626/p/8819119.html)Eigen初始化0.[官网资料](http://eigen.tuxfamily.org/index.php?titleMain_Page)1. Eigen Matlab矩阵定义2. Eigen Matlab基础使用3. Eigen Matlab特殊矩阵生成4. Eigen Matlab矩阵分块…

GitHUb 代码提交遇到的问题以及解决办法

git 添加代码出现以下错误&#xff1a; fatal: Unable to create F:/wamp/www/ThinkPhpStudy/.git/index.lock: File exists. If no other git process is currently running, this probably means a git process crashed in this repository earlier. Make sure no other git …

isContinuous 反色处理

cv::Mat inverseColor5(cv::Mat srcImage) {int row srcImage.rows;int col srcImage.cols;cv::Mat tempImage srcImage.clone();// 判断是否是连续图像&#xff0c;即是否有像素填充if( srcImage.isContinuous() && tempImage.isContinuous() ){row 1;// 按照行展…

阿里云智能对话分析服务

2019独角兽企业重金招聘Python工程师标准>>> 关于智能对话分析服务 智能对话分析服务 (Smart Conversation Analysis) 依托于阿里云语音识别和自然语言分析技术&#xff0c;为企业用户提供智能的对话分析服务&#xff0c;支持语音和文本数据的接入。可用于电话/在线…

【Smooth】非线性优化

文章目录非线性优化0 .case实战0.1求解思路0.2 g2o求解1. 状态估计问题1.1 最大后验与最大似然1.2 最小二乘的引出2. 非线性最小二乘2.1 一阶和二阶梯度法2.2 高斯牛顿法2.2 列文伯格-马夸尔特方法&#xff08;阻尼牛顿法)3 Ceres库的使用4 g2o库的使用非线性优化 0 .case实战…

.net 基于Jenkins的自动构建系统开发

先让我给描述一下怎么叫一个自动构建或者说是持续集成 &#xff1a; 就拿一个B/S系统的合作开发来说&#xff0c;在用SVN版本控制的情况下&#xff0c;每个人完成自己代码的编写&#xff0c;阶段性提交代码&#xff0c;然后测试-修改&#xff0c;最后到所有代码完工&#xff0c…

LUT 查表反色处理

cv::Mat inverseColor6(cv::Mat srcImage) {int row srcImage.rows;int col srcImage.cols;cv::Mat tempImage srcImage.clone();// 建立LUT 反色tableuchar LutTable[256];for (int i 0; i < 256; i)LutTable[i] 255 - i;cv::Mat lookUpTable(1, 256, CV_8U);uchar* p…