std::thread的说明与示例

源于通义千问

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


1. 传递普通函数

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

示例
cpp 复制代码
#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. 传递类的成员函数

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

示例
cpp 复制代码
#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 表达式是一种简洁的方式,尤其适合定义临时逻辑。

示例
cpp 复制代码
#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() 的类实例,可以像函数一样调用。

示例
cpp 复制代码
#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 可以将函数及其参数绑定在一起,生成一个可调用对象。

示例
cpp 复制代码
#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 是一个通用的函数包装器,可以存储任何可调用对象。

示例
cpp 复制代码
#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::function
    std::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> 中。


示例代码

cpp 复制代码
#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 方法直接构造线程对象,并传递多个参数:

      cpp 复制代码
      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)。
相关推荐
yi个名字1 小时前
C++继承:从生活实例谈面向对象的精髓
开发语言·c++·链表
黎明smaly1 小时前
【C语言】复习~动态内存管理
c语言·开发语言·c++·面试
黎明smaly1 小时前
【C语言】复习~数组和指针
c语言·开发语言·数据结构·c++·leetcode
黎相思2 小时前
特殊类设计
开发语言·c++
君鼎2 小时前
C++——volatile
开发语言·c++
Uncertainty!!3 小时前
C++系统IO
开发语言·c++
tanyongxi663 小时前
C++ 继承详解:基础篇(含代码示例)
开发语言·c++
C++chaofan4 小时前
P2089 烤鸡
数据结构·c++·算法
龙湾开发5 小时前
C++ vscode配置c++开发环境
开发语言·c++·笔记·vscode·学习