cpp 线程传递参数

目录

  • 给thread传递参数的 多种情况:

    • 传递字面值
    • 传递字符数组当字符串, 为了安全还是转换成 string 更好.
    • 向线程传递一个引用, 注意需要使用 ref 函数
    • thread 传递函数对象,需要注意,如果在 thread 构造参数里面构造对象,需要用"()"包起来
    • 仿照 bind 将对象的成员函数作为线程的参数
    • 向thread传递指针:普通指针和智能指针, 需要注意安全
    • unique_ptr的movable语义传递参数, 需要使用 move 函数

给thread传递参数的 多种情况:

在创建thread object时,可以向线程传递参数,默认情况下, 参数会被
拷贝到 所创建的线程空间以供线程执行时存取,即使参数是引用也是这样.

传递字面值

void f(int i,const string& s);
thread t(f,3,"hello");  // 字符串常量 "hello",会被转换成string,在新线程中存在.

传递字符数组当字符串, 为了安全还是转换成 string 更好.

void f(int f,const string& s);
void oops(int some){
    char buffer[1024];
    sprintf(buffer,"%d",some);
    thread t(f,3,buffer);  //  换成 thread t(f,3,string(buffer)); 保证安全
    t.detach();
}

这里会存在一个潜在的风险,当oops退出时,新线程中,buffer可能还没有被转换成string,这将会出现一个dangle pointer.
一个解决办法是 构造thread 时,就先将 buffer 转换成 string,并将string拷贝到新线程的地址空间.

向线程传递一个引用, 注意需要使用 ref 函数

class Test {
public:
    Test(int i = 0) :data(i) {}
    Test(const Test& t) {
        data = t.data;
        cout << "Test copy constructor" << endl;
    }
    Test& operator=(const Test& t) {
        data = t.data;
        cout << "Test 赋值构造函数" << endl;
        return *this;
    }

    ~Test() {
        cout << "Test deconstructor" << endl;
    }

public:
    int data;
};

void func(Test& one) {
    cout << "func get the data:" << one.data << endl;
}

void oops() {
    Test one(10);

    // windows 下 不使用ref编译不能通过,除非func方法里面的参数不是引用类型,但是这样会调用几次Test的拷贝构造函数.
    thread t(func,ref(one));    

    t.join();
}

int main()
{
    oops();
    return 0;
}

thread 传递函数对象,需要注意,如果在 thread 构造参数里面构造对象,需要用"()"包起来

class Testor {
public:

    Testor(int d = 0):data(d){}
    Testor(const Testor& other) {
        data = other.data;
    }

    Testor& operator=(const Testor& other) {
        data = other.data;
        return *this;
    }

    void operator()() {
        cout << "Testor::operator() called!" << endl;
    }

public:
    int data;
};

void oops() {
    thread t((Testor()));  // Test() 必须用"()"包起来,否则windows下编译不通过
    t.join();
}

int main()
{
    oops();
    return 0;
}

仿照 bind 将对象的成员函数作为线程的参数

class Testor {
public:

    Testor(int d = 0):data(d){}
    Testor(const Testor& other) {
        data = other.data;
    }

    Testor& operator=(const Testor& other) {
        data = other.data;
        return *this;
    }

    void operator()() {
        cout << "Testor::operator() called!" << endl;
    }

    void show() {
        cout << "Testor show called!" << endl;
    }

public:
    int data;
};

void oops() {
    Testor testor;
    thread t(&Testor::show,&testor);
    t.join();
}

int main()
{
    oops();
    return 0;
}

向thread传递指针:普通指针和智能指针, 需要注意安全

class Testor {
public:

    Testor(int d = 0):data(d){}
    Testor(const Testor& other) {
        data = other.data;
    }

    Testor& operator=(const Testor& other) {
        data = other.data;
        return *this;
    }

    ~Testor() {
        cout << "~Testor called!" << endl;
    }

    void operator()() {
        cout << "Testor::operator() called!" << endl;
    }

    void show() {
        cout << "Testor show called!" << endl;
    }

public:
    int data;
};

void func_1(shared_ptr<Testor> ptr) {
    ptr->data++;
}

void func_2(Testor* ptr) {
    ptr->data++;
}

void oops() {
    shared_ptr<Testor> ptr(new Testor(11));
    thread t1(func_1,ptr);
    t1.join();
    cout << "shared_ptr->data:" << ptr->data << endl;

    auto ptr2 = new Testor(11);
    thread t2(func_2, ptr2);
    t2.join();
    cout << "ptr2->data:" << ptr2->data << endl;
    delete ptr2;
}

int main()
{
    oops();
    return 0;
}

说明:传递指针给线程函数, thread 拷贝的是指针对象本身,所以线程怼指针对象的修改会影响到
主线程中的对象.
注意,智能指针可能会引起对象的生命周期的延长,若是 thread::detach,那么智能指针比普通的
裸指针安全,特别是detach后oops退出,智能指针管理的对象由于引用计数不会被析构,而普通裸
指针由于oops退出析构了局部对象导致dangle pointer.

unique_ptr的movable语义传递参数, 需要使用 move 函数

class Testor {
public:

    Testor(int d = 0):data(d){}
    Testor(const Testor& other) {
        data = other.data;
    }

    Testor& operator=(const Testor& other) {
        data = other.data;
        return *this;
    }

    ~Testor() {
        cout << "~Testor called!" << endl;
    }

    void operator()() {
        cout << "Testor::operator() called!" << endl;
    }

    void show() {
        cout << "Testor show called!" << endl;
    }

public:
    int data;
};

void func_1(shared_ptr<Testor> ptr) {
    ptr->data++;
}

void func_2(Testor* ptr) {
    ptr->data++;
}

void func_3(unique_ptr<Testor> uptr) {
    uptr->data = 44;
    cout << "func_3->data:" << uptr->data << endl;
}

void oops() {

    unique_ptr<Testor> uptr(new Testor(11));

    // 必须要使用 move,否则 windows下编译不过.
    // 因为unique_ptr是个左值对象,move的功能是将左值变成右值使用
    thread t(func_3,move(uptr));
    t.join();

    if (uptr.get()) {
        cout << "main thread:" << uptr->data << endl;
    }
    else {
        cout << "main thread uptr is null!" << endl;  // 将会被打印
    }
}

int main()
{
    oops();
    return 0;
}

说明:std::unique_ptr不能共享所有权,但是可以转移所有权,
采用std::move()语义后原来的std::unique_ptr 将为null.

总结来自:https://blog.csdn.net/liuxuejiang158blog/article/details/17090971

原文地址:https://www.cnblogs.com/daihanlong/p/10261433.html

时间: 2024-10-11 04:56:51

cpp 线程传递参数的相关文章

如何向线程传递参数

Net提供了许多多线程编程工具,可能是因为太多了,所以掌握起来总是有一些头疼,我在这里讲讲我总结的一些多线程编程的经验,希望对大家有帮助 不需要传递参数,也不需要返回参数我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下 ThreadStart threadStart=new ThreadStart(Calculate); Thread thread=new Thread(threadStart); thread.Start(); public void Calculate()

[C++11 并发编程] 03 向线程传递参数

我们可以通过std::thread的构造函数向线程传递参数,但是默认情况下,这些参数的拷贝会被传递到线程内部,即使参数申明为引用,也是如此: void f(int i,std::string const& s); std::thread t(f,3,"hello"); 如上面例子所示,创建了一个线程关联到t,它会调用f(3, "hello"),虽然f的第二个参数类型为std::string,但是实际上字面量hello还是以char const *类型传递到线

线程传递参数

#include "stdio.h" #include "unistd.h" #include "pthread.h"   void *func(void *p) {     int i;     int *a=(int*)p;     for (i=0; i<20; i++)     {         a[i]=100+i;         sleep(1);     }     return NULL; }   int main()

Net线程足迹 传递参数至线程

方法一:应用ParameterizedThreadStart这个委托来传递输入参数,这种方法适用于传递单个参数的情况. [c-sharp] view plaincopy using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using Sys

Jmeter 跨线程组传递参数 之两种方法

终于搞定了Jmeter跨线程组之间传递参数,这样就不用每次发送请求B之前,都需要同时发送一下登录接口(因为同一个线程组下的请求是同时发送的),只需要发送一次登录请求,请求B直接用登录请求的参数即可,直到登录接口的参数失效了,需再次发送一次登录接口,又可以多次使用其参数,下面举例子: 1.登录接口中利用 Json Path Extractor 获取到登录接口的响应参数,(怎么获取上一节讲过) 终于搞定了Jmeter跨线程组之间传递参数,这样就不用每次发送请求B之前,都需要同时发送一下登录接口(因为

Linux线程体传递参数的方法详解

传递参数的两种方法 线程函数只有一个参数的情况:直接定义一个变量通过应用传给线程函数. 例子 #include #include using namespace std; pthread_t thread; void * fn(void *arg) { int i = *(int *)arg; cout<<"i = "<<i<<endl; return ((void *)0); } int main() { int err1; int i=10; e

如何在调用线程的时候传递参数

我们在写Remoting程序或者其他的一些应用程序的时候难免要和线程打交道,.Net使我们很容易就可以创建一个线程,但是它提供的创建线程和启动线程的方法没有明显的提供参数,假如我们要用线程来启动类里面一个带参数的方法该怎么办?下面就简单的介绍如何使用.NET提供的丰富的框架来实现这个功能.为了可以生动详细的介绍整个过程,我建立下面的一个.NET类,它也是要用线程启动的方法的载体.类如下所示: using System; namespace WindowsApplication1 { /// <s

[存]Jmeter 如何实现跨线程组传递参数

此文来源与组里小白的分享~ Jmeter 如何实现跨线程组传递参数(以传递token为例)   1.首先选择一个登陆接口(线程组1),添加正则表达式提取器提取token,接着再添加一个后置处理器BeanShell PostProcessor 2.BeanShell PostProcessor中参数项输入引用变量${token};脚本项输入动作语句${__setProperty(token1,${token},)}; 3.在线程组2添加一个前置处理器BeanShell PreProcessor 4

C#传递参数到线程的n个方法

[转]http://kb.cnblogs.com/a/888688/ 本片文章的议题是有关于传递参数到线程的几种方法. 首先我们要知道什么是线程,什么时候要用到线程,如何去使用线程,如何更好的利用线程来完成工作.线程是程序可执行片段的最小单元,是组成运行时程序的基本单元,一个进程有至少一个线程组成.一般在并行处理等待事件的时候要用到线程,如等待网络响应,等待I/O通讯,后台事务处理等情况.使用线程其实很简单,在.net框架下面你首先要定义一个函数来完成一些工作,然后实例化一个线程对象Thread