首页 > 其他分享 >向线程函数传递参数

向线程函数传递参数

时间:2024-03-24 21:11:37浏览次数:17  
标签:std widget 函数 thread 参数 线程 data string

向 std::thread 构造函数中的可调用对象, 或函数传递一个参数很简单。 需要注意的是, 默认参数要拷贝到线程独立内存中, 即使参数是引用的形式, 也可以在新线程中进行访问 。

void f(int i, std::string const& s);
std::thread t(f, 3, "hello");

代码创建了一个调用f(3, "hello")的线程。 注意, 函数f需要一个 std::string 对象作为第二个参数, 但这里使用的是字符串的字面值, 也就是 char const * 类型。 之后, 在线程的上下文中完成字面值向 std::string 对象的转化。 需要特别要注意, 当指向动态变量的指针作为参数传递给线程的情况, 代码如下: 

void f(int i,std::string const& s);
void oops(int some_param)
{
    char buffer[1024]; // 1
    sprintf(buffer, "%i",some_param);
    std::thread t(f,3,buffer); // 2
    t.detach();
}

这种情况下, buffer②是一个指针变量, 指向本地变量, 然后本地变量通过buffer传递到新线程中②。 并且, 函数有很有可能会在字面值转化成 std::string 对象之前崩溃(oops), 从而导致一些未定义的行为。 并且想要依赖隐式转换将字面值转换为函数期待的 std::string 对象,但因 std::thread 的构造函数会复制提供的变量, 就只复制了没有转换成期望类型的字符串字面值。 

 解决方案就是在传递到 std::thread 构造函数之前就将字面值转化为 std::string 对象: 

void f(int i,std::string const& s);
void not_oops(int some_param)
{
    char buffer[1024];
    sprintf(buffer,"%i",some_param);
    std::thread t(f,3,std::string(buffer)); // 使用std::string, 避免悬垂指针
    t.detach();
}

不过, 也有成功的情况: 复制一个引用。 在线程更新数据结构时, 会成功的传递一个引用: 

void update_data_for_widget(widget_id w,widget_data& data); // 1
void oops_again(widget_id w)
{
    widget_data data;
    std::thread t(update_data_for_widget,w,data); // 2
    display_status();
    t.join();
    process_widget_data(data); // 3
}

虽然update_data_for_widget①的第二个参数期待传入一个引用, 但是 std::thread 的构造函数②并不知晓; 构造函数无视函数期待的参数类型, 并盲目的拷贝已提供的变量。 当线程调用update_data_for_widget函数时, 传递给函数的参数是data变量内部拷贝的引用, 而非数据本身的引用。 因此, 当线程结束时, 内部拷贝数据将会在数据更新阶段被销毁, process_widget_data将会接收到没有修改的data变量③。 可以使用 std::ref 将参数转换成引用的形式, 从而可将线程的调用改为以下形式: 

std::thread t(update_data_for_widget,w,std::ref(data));

 在这之后, update_data_for_widget就会接收到一个data变量的引用, 而非一个data变量拷贝的引用。 

标签:std,widget,函数,thread,参数,线程,data,string
From: https://www.cnblogs.com/love-9/p/18093065

相关文章

  • 第9讲:函数递归
    第9讲:函数递归1.递归是什么?1.1递归的思想:1.2递归的限制条件2.递归举例2.1举例1:求n的阶乘2.1.1分析和代码实现2.1.2画图推演2.2举例2:2.2.1分析和代码实现2.2.2画图推演3.递归与迭代1.递归是什么?递归是学习C语言函数绕不开的⼀个话题,那什么是递归呢?递......
  • 等待线程完成
     如果不等待线程,就必须保证线程结束之前,可访问的数据得有效性。 这种情况很可能发生在线程还没结束,函数已经退出的时候,这时线程函数还持有函数局部变量的指针或引用。 structfunc{int&i;func(int&i_):i(i_){}voidoperator()(){fo......
  • 线程启动
     线程在std::thread对象创建(为线程指定任务)时启动。最简单的情况下,任务也会很简单,通常是无参数无返回(void-returning)的函数 。 使用C++线程库启动线程,可以归结为构造std::thread对象: voiddo_some_work();std::threadmy_thread(do_some_work);为了让编译器识......
  • Scala函数练习题
    1、定义一个高阶函数,按照指定的规则对集合里面的每个元素进行操作比如:Array(“hh”,“red”,“java”,“hadoop”)规则:对集合中每个元素进行操作,得到集合每个元素的长度objecttest{defmain(args:Array[String]):Unit={vallist=Array("hh","red","ja......
  • 详解rtklib中main函数如何配置文件(下)
    目录一、main函数流程总结二、分析识别-k后如何配置三、最后传参的数据文件处理方式 一、main函数流程总结详解rtklib中main函数如何配置文件(上)-CSDN博客在这片文章中讲解了rtklib中main函数的整个流程。(1)通过两种方法给main函数传递参数,并放在argv这个指针数组......
  • 简易的取款多线程
    首先建立一个classAccount类,设置全局变量money,这个变量会被所有的线程使用。设置条件。classAccount{publicstaticintmoney=3000;//建立全局变量publicsynchronizedvoidtaking(intm){if(m>money){System.out.println("余额不足");}else{System.out.pr......
  • 初识C++(二)引用,内联函数,auto
    目录1.引用的概念与用法:1.1引用特性:1.2使用场景    1.2.1做参数1.3传值、传引用效率比较1.4引用做返回值1.5引用和指针的对比2.内联函数3.auto关键字4.基于范围的for循环(C++11)5.指针空值nullptr(C++11)1.引用的概念与用法:    引用是一个重要的......
  • 直方图和密度函数——Python实现
    概率密度函数是概率论核心概念之一,用于描述连续型随机变量所服从的概率分布,是概率计算的通用表达。研究一个随机变量,不只是要看它能取哪些值,更重要的是它取各种值的概率如何!在实际使用时对应离散化后的频率。也可以这样理解,概率密度函数是数学通用表达的频率,而统计学中的频率是将......
  • 10_FreeRTOS任务相关API函数
    FreeRTOS任务相关API函数FreeRTOS任务相关API函数介绍UBaseType_tuxTaskPriorityGet(constTaskHandle_txTask)voidvTaskPrioritySet(TaskHandle_txTask,UBaseType_tuxNewPriority)UBaseType_tuxTaskGetNumberOfTasks(void)uxTaskGetSystemStatevTaskGe......
  • JAVAEE——多线程的设计模式,生产消费模型,阻塞队列
    文章目录多线程设计模式什么是设计模式单例模式饿汉模式懒汉模式线程安全问题懒汉模式就一定安全吗?锁引发的效率问题jvm的优化引起的安全问题阻塞队列阻塞队列是什么?生产消费者模型阻塞队列实现消费生产者模型可能遇到的异常多线程设计模式什么是设计模式首先我......