std::thread的说明与示例

源于通义千问

在 C++ 中,std::thread 支持传递多种类型的函数作为线程入口点。你可以传递普通函数、类的成员函数、Lambda 表达式、函数对象(仿函数)等。以下是详细的说明和示例。


1. 传递普通函数

普通函数是最简单的用法。

示例
#include <iostream>
#include <thread>void myFunction(int x) {std::cout << "Thread ID: " << std::this_thread::get_id()<< ", Value: " << x << std::endl;
}int main() {// 创建线程并传递普通函数std::thread t(myFunction, 42);// 等待线程完成if (t.joinable()) {t.join();}return 0;
}
输出
Thread ID: 140735212345678, Value: 42

2. 传递类的成员函数

传递类的成员函数时,需要提供类实例的指针或引用。

示例
#include <iostream>
#include <thread>class MyClass {
public:void memberFunction(int x) {std::cout << "Thread ID: " << std::this_thread::get_id()<< ", Value: " << x << std::endl;}
};int main() {MyClass obj;// 创建线程并传递成员函数std::thread t(&MyClass::memberFunction, &obj, 42);// 等待线程完成if (t.joinable()) {t.join();}return 0;
}
输出
Thread ID: 140735212345678, Value: 42

3. 传递 Lambda 表达式

Lambda 表达式是一种简洁的方式,尤其适合定义临时逻辑。

示例
#include <iostream>
#include <thread>int main() {int value = 42;// 使用 Lambda 表达式创建线程std::thread t([value]() {std::cout << "Thread ID: " << std::this_thread::get_id()<< ", Value: " << value << std::endl;});// 等待线程完成if (t.joinable()) {t.join();}return 0;
}
输出
Thread ID: 140735212345678, Value: 42

4. 传递函数对象(仿函数)

函数对象是重载了 operator() 的类实例,可以像函数一样调用。

示例
#include <iostream>
#include <thread>class Functor {
public:void operator()(int x) const {std::cout << "Thread ID: " << std::this_thread::get_id()<< ", Value: " << x << std::endl;}
};int main() {Functor f;// 创建线程并传递函数对象std::thread t(f, 42);// 等待线程完成if (t.joinable()) {t.join();}return 0;
}
输出
Thread ID: 140735212345678, Value: 42

5. 传递绑定器(std::bind

使用 std::bind 可以将函数及其参数绑定在一起,生成一个可调用对象。

示例
#include <iostream>
#include <thread>
#include <functional>void myFunction(int x) {std::cout << "Thread ID: " << std::this_thread::get_id()<< ", Value: " << x << std::endl;
}int main() {// 使用 std::bind 绑定函数和参数auto boundFunction = std::bind(myFunction, 42);// 创建线程并传递绑定器std::thread t(boundFunction);// 等待线程完成if (t.joinable()) {t.join();}return 0;
}
输出
Thread ID: 140735212345678, Value: 42

6. 传递可调用对象(如 std::function

std::function 是一个通用的函数包装器,可以存储任何可调用对象。

示例
#include <iostream>
#include <thread>
#include <functional>void myFunction(int x) {std::cout << "Thread ID: " << std::this_thread::get_id()<< ", Value: " << x << std::endl;
}int main() {// 使用 std::function 存储可调用对象std::function<void()> callable = std::bind(myFunction, 42);// 创建线程并传递 std::functionstd::thread t(callable);// 等待线程完成if (t.joinable()) {t.join();}return 0;
}
输出
Thread ID: 140735212345678, Value: 42

总结

  • 普通函数:直接传递函数名。
  • 类的成员函数:需要提供类实例的指针或引用。
  • Lambda 表达式:适合定义临时逻辑。
  • 函数对象:重载 operator() 的类实例。
  • 绑定器(std::bind:用于绑定函数和参数。
  • std::function:通用的函数包装器。

多个线程、多个参数

在 C++ 中,如果需要通过 std::thread 传递多个参数给类的成员函数,可以直接将这些参数依次传递给线程构造函数。std::thread 会自动将这些参数转发给目标函数。

以下是详细的示例,展示如何传递多个参数给类的成员函数,并将其存储在 std::vector<std::thread> 中。


示例代码

#include <iostream>
#include <thread>
#include <vector>class MyClass {
public:// 成员函数,接受多个参数void memberFunction(int threadId, const std::string& message, double value) {std::cout << "Thread ID: " << std::this_thread::get_id()<< ", Thread Number: " << threadId<< ", Message: " << message<< ", Value: " << value << std::endl;}
};int main() {const int numThreads = 5; // 线程数量MyClass myClassInstance;  // 类实例std::vector<std::thread> threads; // 存储线程的容器// 创建多个线程并传递多个参数给类的成员函数for (int i = 0; i < numThreads; ++i) {threads.emplace_back(&MyClass::memberFunction, &myClassInstance,i, "Hello from thread", 3.14 + i);}// 等待所有线程完成for (auto& t : threads) {if (t.joinable()) {t.join();}}std::cout << "All threads finished." << std::endl;return 0;
}

代码解析

  1. 类定义

    • 定义了一个类 MyClass,其中包含一个成员函数 memberFunction,该函数接受三个参数:
      • int threadId:线程编号。
      • const std::string& message:字符串消息。
      • double value:浮点数值。
  2. 创建类实例

    • main 函数中,创建了 MyClass 的实例 myClassInstance
  3. 创建线程

    • 使用 std::vector<std::thread> 存储多个线程。
    • 使用 emplace_back 方法直接构造线程对象,并传递多个参数:
      threads.emplace_back(&MyClass::memberFunction, &myClassInstance,i, "Hello from thread", 3.14 + i);
      
      • 第一个参数是成员函数的指针:&MyClass::memberFunction
      • 第二个参数是类实例的地址:&myClassInstance
      • 后续参数是传递给成员函数的多个参数:i(当前线程编号)、"Hello from thread"(字符串)和 3.14 + i(浮点数)。
  4. 等待线程完成

    • 遍历 threads 容器,调用每个线程的 join() 方法,确保主线程等待所有子线程完成。

输出示例

运行程序后,输出可能如下(线程 ID 可能不同):

Thread ID: 140735212345678, Thread Number: 0, Message: Hello from thread, Value: 3.14
Thread ID: 140735212345789, Thread Number: 1, Message: Hello from thread, Value: 4.14
Thread ID: 140735212345890, Thread Number: 2, Message: Hello from thread, Value: 5.14
Thread ID: 140735212345991, Thread Number: 3, Message: Hello from thread, Value: 6.14
Thread ID: 140735212346092, Thread Number: 4, Message: Hello from thread, Value: 7.14
All threads finished.

注意事项

  1. 参数类型匹配

    • 确保传递给线程的参数类型与目标函数的参数类型匹配。例如,如果函数参数是引用类型(如 const std::string&),则可以传递临时对象或变量。
  2. 参数拷贝与移动

    • 如果传递的是复杂对象(如自定义类或容器),注意对象的拷贝或移动行为。可以通过 std::refstd::move 显式控制。
  3. 线程安全

    • 如果多个线程访问共享资源(如类的成员变量),需要使用互斥锁(std::mutex)或其他同步机制来确保线程安全。
  4. C++11 及以上版本

    • 上述代码需要 C++11 或更高版本支持。确保编译器支持 C++11,并使用适当的编译选项(例如 -std=c++11)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Day38】

DAY 38 Dataset和Dataloader类 对应5. 27作业 知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 作业&#xff1a;了解下cifar数据集&#xff0c;尝试获取其中一张图片 import …

RabbitMQ 集群与高可用方案设计(三)

五、高可用方案设计与实现 &#xff08;一&#xff09;负载均衡与代理 1. HAProxy 配置 HAProxy 是一款广泛应用的开源负载均衡器和代理服务器&#xff0c;它能够实现对 RabbitMQ 集群节点的负载均衡和健康检查&#xff0c;有效提高系统的可用性和性能。以下是使用 HAProxy …

机器学习第二十四讲:scikit-learn → 机器学习界的瑞士军刀

机器学习第二十四讲&#xff1a;scikit-learn → 机器学习界的瑞士军刀 资料取自《零基础学机器学习》。 查看总目录&#xff1a;学习大纲 关于DeepSeek本地部署指南可以看下我之前写的文章&#xff1a;DeepSeek R1本地与线上满血版部署&#xff1a;超详细手把手指南 Scikit-…

百度ocr的简单封装

百度ocr地址 以下代码为对百度ocr的简单封装,实际使用时推荐使用baidu-aip 百度通用ocr import base64 from enum import Enum, unique import requests import logging as logunique class OcrType(Enum):# 标准版STANDARD_BASIC "https://aip.baidubce.com/rest/2.0…

Ubuntu20.04 gr-gsm完整安装教程

gr-gsm完整安装教程 安装gnuradio3.8安装依赖项指定gnuradio源安装gnuradio 安装gr-gsm安装依赖项安装gr-gsm修改环境变量 安装成功 安装gnuradio3.8 安装依赖项 sudo apt install git cmake g libboost-all-dev libgmp-dev swig python3-numpy python3-mako python3-sphinx …

(自用)Java学习-5.15(模糊搜索,收藏,购物车)

1. 模糊搜索商品功能 前端实现&#xff1a; 通过解析URL参数&#xff08;如search联想&#xff09;获取搜索关键字&#xff0c;发送AJAX GET请求到后端接口/product/searchGoodsMessage。 动态渲染搜索结果&#xff1a;若结果非空&#xff0c;循环遍历返回的商品数据&#xff…

STM32 TIM 定时器深度剖析:结构、时基、中断与应用开发(超形象详解)

文章目录 定时器&#xff08;TIM&#xff09;定时器种类与分布定时器的基本结构时基单元时基单元基本结构计数器计数方向时基单元时钟来源计算寄存器预加载机制 自制延时函数获取单片机当前时间实现延迟函数初始化定时器3的时基单元配置中断编写中断响应函数测试延迟函数 定时器…

Java使用minio上传整个目录下的所有内容

目录 1、添加相关配置 2、添加依赖 3、实现方法 1️⃣基础版&#xff1a; 2️⃣优化版&#xff08;推荐使用&#xff09;&#xff1a; 3️⃣上传远程主机上的目录内容&#xff1a; 4️⃣直接上传远程主机中的目录内容 业务背景&#xff1a;需要需要minio进行上传指定目录下所有…

Python的分布式网络爬虫系统实现

1. 系统架构概述 一个典型的分布式网络爬虫系统通常包含以下几个核心组件&#xff1a; 1.主节点&#xff08;Master Node&#xff09;&#xff1a; 任务调度&#xff1a;负责将抓取任务分配给各个工作节点。URL 管理&#xff1a;维护待抓取的 URL 队列和已抓取的 URL 集合&a…

AI工具的选择:Dify还是传统工具?

从纯技术视角出发&#xff0c;选择Dify还是传统开发工具需要基于六个核心维度进行理性决策。以下为结构化分析框架&#xff0c;附典型场景示例&#xff1a; 1. 开发效率 vs 控制力权衡矩阵 维度Dify优势场景传统工具优势场景迭代速度需求明确的标准CRUD&#xff08;如后台管理…

2.3 TypeScript 非空断言操作符(后缀 !)详解

在 TypeScript 中&#xff0c;当你开启了严格的空值检查&#xff08;strictNullChecks&#xff09;后&#xff0c;变量如果可能是 null 或 undefined&#xff0c;就必须在使用前进行显式的判断。为了在某些场景下简化代码&#xff0c;TypeScript 提供了非空断言操作符&#xff…

深度学习:损失函数与激活函数全解析

目录 深度学习中常见的损失函数和激活函数详解引言一、损失函数详解1.1 损失函数的作用与分类1.2 回归任务损失函数1.2.1 均方误差&#xff08;MSE&#xff09;1.2.2 平均绝对误差&#xff08;MAE&#xff09; 1.3 分类任务损失函数1.3.1 交叉熵损失&#xff08;Cross-Entropy&…

掌握 npm 核心操作:从安装到管理依赖的完整指南

图为开发者正在终端操作npm命令&#xff0c;图片来源&#xff1a;Unsplash 作为 Node.js 生态的基石&#xff0c;npm&#xff08;Node Package Manager&#xff09;是每位开发者必须精通的工具。每天有超过 1700 万个项目通过 npm 共享代码&#xff0c;其重要性不言而喻。本文…

Elasticsearch的运维

Elasticsearch 运维工作详解&#xff1a;从基础保障到性能优化 Elasticsearch&#xff08;简称 ES&#xff09;作为分布式搜索和分析引擎&#xff0c;其运维工作需要兼顾集群稳定性、性能效率及数据安全。以下从核心运维模块展开说明&#xff0c;结合实践场景提供可落地的方案…

国产三维CAD皇冠CAD(CrownCAD)建模教程:汽车电池

在线解读『汽车电池』的三维建模流程&#xff0c;讲解3D草图、保存实体、拉伸凸台/基体、设置外观等操作技巧&#xff0c;一起和皇冠CAD&#xff08;CrownCAD&#xff09;学习制作步骤吧&#xff01; 汽车电池&#xff08;通常指铅酸蓄电池或锂离子电池&#xff09;是车辆电气系…

深入理解 JDK、JRE 和 JVM 的区别

在 Java 中&#xff0c;JDK、JRE 和 JVM 是非常重要的概念&#xff0c;它们各自扮演着不同的角色&#xff0c;却又紧密相连。今天&#xff0c;就让我们来详细探讨一下它们之间的区别。 一、JVM JVM 即 Java 虚拟机&#xff0c;它是整个 Java 技术体系的核心。JVM 提供了 Java…

云电脑显卡性能终极对决:ToDesk云电脑/顺网云/海马云,谁才是4K游戏之王?

一、引言 1.1 云电脑的算力革命 云电脑与传统PC的算力供给差异 传统PC的算力构建依赖用户一次性配置本地硬件&#xff0c;特别是CPU与显卡&#xff08;GPU&#xff09;。而在高性能计算和游戏图形渲染等任务中&#xff0c;GPU的能力往往成为决定体验上限的核心因素。随着游戏分…

撤销Conda初始化

在安装miniconda3的过程中&#xff0c;最后系统会出现这一行提示用户可以选择自动初始化&#xff0c;这样的话&#xff0c;系统每次启动就会自动启动基础&#xff08;base&#xff09;环境。 但是我们也可以通过 conda init --reverse $shell 来撤销 Conda 的初始化设置。这将恢…

Flask-SQLAlchemy数据库查询:query

1、为什么可以用 模型类.query 来查询数据库&#xff1f; 在 Flask 中使用 SQLAlchemy ORM 时&#xff0c;所有继承自 db.Model 的模型类都会自动获得一个 query 属性。 其本质是 db.session.query(模型类) 的快捷方式&#xff0c;无需显式操作 db.session。 代码示例&#…

【免费】【无需登录/关注】度分秒转换在线工具

UVE Toolbox 功能概述 这是一个用于地理坐标转换的在线工具&#xff0c;支持两种转换模式&#xff1a; 十进制度 → 度分秒 度分秒 → 十进制度 使用方法 十进制度转度分秒 在"经度"输入框中输入十进制度格式的经度值&#xff08;例如&#xff1a;121.46694&am…