首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >线程入口函数的传参方式

线程入口函数的传参方式

原创
作者头像
金莲与饼皆失
发布2025-09-09 20:42:09
发布2025-09-09 20:42:09
10500
代码可运行
举报
文章被收录于专栏:Linux进程与线程Linux进程与线程
运行总次数:0
代码可运行

线程的启动,也就是线程入口函数的传递方式。虽然函数接口中有多种形式,可以创建无参对象(线程没有入口函数,也就是线程不做任务),但是这种没有什么意义,一般不使用;可以将两外一个线程对象移动过来,但是移动之后,另外一个线程对象就没有了,这种一般用的也不多,接下来我们重点研究第三种接口形式。

在C++11中,将线程封装成了类的概念,下面就是线程类的构造函数形式。

代码语言:cpp
代码运行次数:0
运行
复制
thread() noexcept; //(1)无参对象

thread( thread&& other ) noexcept; //(2)移动构造

template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args ); //(3) 可变参数的形式,f就是线程入口函数,args就是f的传参
// bind也可以传递可变参数
// thread的传参与std::bind的传参类似,所以thread的传参可以传占位符;默认也是采用值传递,如果需要使用引用,可以使用引用的包装器std::ref/std::cref
thread(const thread&) = delete;//(4)没有拷贝构造函数
// 因为线程id是唯一的

如何获取线程id

代码语言:cpp
代码运行次数:0
运行
复制
/*
    获取线程id会有成员函数get_id;
    可以使用std::this_thread中的函数get_id获取线程id;
*/

创建线程并执行

代码语言:cpp
代码运行次数:0
运行
复制
#include <iostream>
#include <thread>
#include <unistd.h>
using std::thread;
using std::cout;
using std::endl;

void threadFunc(void){
    cout << "void threadFunc(void)" << endl;
}

int main(int argc, char * argv[]){
    thread myTh(threadFunc); // 创建线程对象
    // 1、让主线程睡眠一段时间,让子线程有足够的时间执行
    // 2、通过在主线程中添加死循环,让子线程有机会执行
    
    cout << "1111" << endl;
    // 3.让主线程等待子线程的执行
    myTh.join();
    /*
    1111
    void threadFunc(void)
    finish main...
    */
    cout << "finish main..." << endl;
    /*while(1){}
      1111
      finish main...
      void threadFunc(void)
    */
    /*
    sleep(10);
    1111
    void threadFunc(void)
    terminate called without an active exception
    已中止 (核心已转储)
    */
    return 0;
}

C++11 的std::thread构造函数提供了非常强大和灵活的传参机制,其核心原则是:直接传递,自动转发

核心机制:完美转发 (Perfect Forwarding)

std::thread 的构造函数是一个变长模板,使用完美转发技术。这意味着:

  1. 直接传递:你只需要将线程函数所需的参数按顺序、按类型直接写在 std::thread 的构造函数中即可。
  2. 值或引用:你可以传递值、引用、常量引用,甚至右值引用。std::thread 会尽力保持参数的本意。

主要的传参方式及注意事项

1. 按值传递 (Pass by Value)

这是最简单、最安全的方式。参数会被拷贝到线程的内部存储中。

  • 用法:直接传递参数的值。
  • 优点:安全,无生命周期问题。线程拥有参数的独立副本。
  • 缺点:如果参数很大,拷贝可能带来性能开销。
代码语言:cpp
代码运行次数:0
运行
复制
void threadFunc(int x){
    cout << "child2 thread id = " << std::this_thread::get_id() << endl;
    cout << "void thread()" << endl;
    cout << "x = " << x << endl;
}

int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    thread myTh(threadFunc,1); // 创建了线程,并且启动入口函数
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
输出结果:
main thread id = 128022756660160
child thread id = 128022749378112
child2 thread id = 128022749378112
void thread()
x = 1
finish main...
*/

2.引用传递 (Pass by Reference)

如果你想在线程中修改原始数据,或者避免拷贝大对象,需要使用引用。但必须格外小心!

用法:使用 std::ref()std::cref() 包装器来明确表示要传递引用。

std::ref(arg): 生成一个 arg 的可修改引用包装器。

std::cref(arg): 生成一个 arg 的常量引用(const reference)包装器。

重要警告:你必须确保被引用参数的生存期超过线程的执行时间,否则会导致未定义行为(通常是崩溃)。

代码语言:cpp
代码运行次数:0
运行
复制
void threadFunc(int x){
    cout << "child2 thread id = " << std::this_thread::get_id() << endl;
    cout << "void thread()" << endl;
    cout << "x = " << x << endl;
}

int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    // 定义引用类型
    typedef void(&rftr)(int);
    rftr f = threadFunc;
    thread myTh(f,3);
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
    输出结果
    main thread id = 134538343646144
    child2 thread id = 134538336400960
    void thread()
    x = 3
    child thread id = 134538336400960
    finish main...
*/
3. 传递指针 (Passing Pointers)

传递指针本质上是按值传递(传递的是地址这个值)。但和引用一样,存在生命周期和数据竞争的问题。

  • 用法:直接传递指针。
  • 警告:同样要确保指针所指向对象的生存期,并且要注意线程安全问题。
代码语言:cpp
代码运行次数:0
运行
复制
void threadFunc(int x){
    cout << "child2 thread id = " << std::this_thread::get_id() << endl;
    cout << "void thread()" << endl;
    cout << "x = " << x << endl;
}

int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    // 定义函数指针
    typedef void(*pFunc)(int); // 定义函数指针
    pFunc f = threadFunc; // 函数指针指向threadFunc
    thread myTh(f,2); // 创建了线程,并且启动入口函数
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
输出结果
main thread id = 137969113899968
child thread id = 137969107203648
child2 thread id = 137969107203648
void thread()
x = 2
finish main...
*/

4.传递成员函数

代码语言:cpp
代码运行次数:0
运行
复制
class Example{
public:
    void threadFunc(int x){
    cout << "child2 thread id = " << std::this_thread::get_id() << endl;
    cout << "void thread()" << endl;
    cout << "x = " << x << endl;
  }
};

int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    // 联想bind函数
    Example ex;
    thread myTh(&Example::threadFunc,&ex,4);
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
输出结果
main thread id = 125797603070912
child thread id = 125797595608640
child2 thread id = 125797595608640
void thread()
x = 4
finish main...
*/

5.使用函数对象的方式

代码语言:cpp
代码运行次数:0
运行
复制
class Example{
public:
    void operator()(int x){
        cout << "child2 thread id = " << std::this_thread::get_id() << endl;
        cout << "void thread()" << endl;
        cout << "x = " << x << endl;
    }
};
int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    Example ex;
    thread myTh(ex,5);
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
输出结果:
main thread id = 126747620344768
child thread id = 126747613853248
child2 thread id = 126747613853248
void thread()
x = 5
finish main...
*/

6.lambda表达式

传递可调用对象 (如 Lambda 表达式)

Lambda 可以捕获局部变量,这是一种非常方便的“传参”方式。

按值捕获:捕获的变量被拷贝到 Lambda 对象中,安全。

按引用捕获:极其危险! 你必须确保被捕获引用的变量生命周期足够长。

代码语言:cpp
代码运行次数:0
运行
复制
int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    thread myTh([](int x){
        cout << "child2 thread id = " << std::this_thread::get_id() << endl;
        cout << "void thread()" << endl;
        cout << "x = " << x << endl;
    },6);
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
    输出结果
    main thread id = 125488134484928
    child thread id = 125488127276608
    child2 thread id = 125488127276608
    void thread()
    x = 6
    finish main...
*/

7.使用function接受lambda表达式的返回值

代码语言:cpp
代码运行次数:0
运行
复制
// 使用函数包装器
int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    // 接收lambda的返回值
    function<void(int)> f = [](int x){
        cout << "child2 thread id = " << std::this_thread::get_id() << endl;
        cout << "void thread()" << endl;
        cout << "x = " << x << endl;
    };
    thread myTh(f,7);
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
输出结果
main thread id = 134957241263040
child thread id = 134957234124352
child2 thread id = 134957234124352
void thread()
x = 7
finish main...
*/

8.使用bind函数作为参数传入

代码语言:cpp
代码运行次数:0
运行
复制
void threadFunc(int x){
    cout << "child2 thread id = " << std::this_thread::get_id() << endl;
    cout << "void thread()" << endl;
    cout << "x = " << x << endl;
}
int main(int argc, char * argv[]){
    cout << "main thread id = " << std::this_thread::get_id() << endl;
    thread myTh(bind(&threadFunc,8));
    cout << "child thread id = " << myTh.get_id() << endl;
    myTh.join();
    cout << "finish main..." << endl;
    return 0;
}
/*
输出结果
main thread id = 129025456661440
child thread id = 129025450178112
child2 thread id = 129025450178112
void thread()
x = 8
finish main...
*/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 核心机制:完美转发 (Perfect Forwarding)
  • 主要的传参方式及注意事项
    • 1. 按值传递 (Pass by Value)
    • 3. 传递指针 (Passing Pointers)
  • 4.传递成员函数
  • 5.使用函数对象的方式
  • 6.lambda表达式
  • 7.使用function接受lambda表达式的返回值
  • 8.使用bind函数作为参数传入
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档