线程传参与返回值

内容介绍

线程函数可以接收参数,但参数默认会被复制到线程内部。引用传递、指针传递和返回值都需要特别处理生命周期。

值传递

#include <iostream>
#include <thread>
#include <string>
 
void print(std::string text) {
    std::cout << text << '\n';
}
 
int main() {
    std::thread t(print, "hello");
    t.join();
}

引用传递

需要用 std::ref 明确告诉 std::thread 传引用。

#include <iostream>
#include <thread>
#include <functional>
 
void add(int& value) {
    value += 1;
}
 
int main() {
    int number = 1;
    std::thread t(add, std::ref(number));
    t.join();
    std::cout << number << '\n';
}

lambda 捕获

int value = 10;
std::thread t([value] {
    std::cout << value << '\n';
});
t.join();

跨线程优先按值捕获。按引用捕获必须保证引用对象在线程结束前仍然活着。

返回值

std::thread 本身不直接返回值。返回值可以使用 cppfuture和promise,或者共享变量配合锁。

最佳代码实践

  • 跨线程传参优先值传递。
  • 引用传递必须用 std::ref,并保证生命周期。
  • 复杂对象优先用 std::shared_ptr 表达共享所有权。
  • 返回值优先用 std::future,不要手写共享变量加忙等。

常见错误用法

void change(int& x) {
    x = 100;
}
 
int main() {
    int value = 0;
    std::thread t(change, value); // 错误:这里会尝试复制,不是传引用
    t.join();
}

正确写法:

std::thread t(change, std::ref(value));

注意事项

  • 线程参数会先 decay-copy,数组会退化,引用会丢失。
  • std::ref 只解决引用传递,不解决生命周期问题。
  • 线程异常不会自动传回主线程,主线程需要通过 future 或异常捕获机制处理。

学习路径