线程传参要保证传入类型正确,避免不必要的错误
#include <iostream>
#include <queue>
#include <thread>
#include <string>
void do_something(std::string s){
std::cout << s;
}
int main()
{
char buffer[1000] = "123456";
std::thread t(do_something, std::string(buffer)); // 先转为string类型 避免悬垂指针
t.detach();
return 0;
}
1.在某些老版本的编译器上会支持下面的写法, 但是会引起错误;
2.在新版本编译器上实测vs2017(C++17标准),下列代码会直接编译报错 error C2672: “std::invoke”: 未找到匹配的重载函数.
#include <thread>
#include <iostream>
void do_something(int &a){ // 2.这里被传入的是a变量副本的引用,不是原始a的引用
a = 15;
std::cout << a;
}
int main()
{
int a = 10;
std::thread t(do_something, a); // 1.拷贝a变量的副本
std::cout << a; // 3.a的值仍然为10
t.join();
return 0;
}
正确写法
#include <thread>
#include <iostream>
void do_something(int &a){
a = 15;
std::cout << a;
}
int main()
{
int a = 10;
std::thread t(do_something, std::ref(a)); // 传入引用参数使用 std::ref
std::cout << a; // 输出值为15
t.join();
return 0;
}
将对象的成员函数作为线程函数
#include <thread>
#include <iostream>
class X
{
public:
void do_lengthy_work(int a) {
std::cout << a;
};
};
int main() {
int num = 0;
X *my_x = new X();
std::thread t(&X::do_lengthy_work, my_x, num);
t.join();
delete my_x;
my_x = nullptr;
return 0;
}
大数据类型成员函数的优化写法
#include <iostream>
#include <thread>
class big_object_class
{
int my_data[10000];
public:
void prepare_data(int a) {
for (int i = 0; i < 10000; ++i) {
my_data[i] = a;
}
};
};
void process_big_object(std::unique_ptr<big_object_class> p) {
std::cout << "process_big_object\n";
}
int main() {
// 初始化大数据类型
std::unique_ptr<big_object_class> p(new big_object_class);
p->prepare_data(42);
// 使用move避免线程启动整体拷贝大数据类型,提升效率
std::thread t(process_big_object, std::move(p));
t.join();
// 原始p指针变量不可用,变为nullptr
if (p == nullptr) {
std::cout << "p = nullptr\n";
}
return 0;
}