线程

std::make_unique<std::thread>(…)结合智能指针和线程管理

本质就做了三件事情:

  • 创建一个线程(thread)
  • 把这个线程对象放在堆上(heap)
  • 用一个“会自动帮你收尾”的智能指针来管理它

线程对象

std::thread就是一个c++标准库的类

在 C++ 中,一个线程对象就是:

1
std::thread t(func);

意思是:

“启动一个新线程,让它从 func 开始执行”

其中创建线程在栈和堆上有所不同:

1
2
3
void f() {
std::thread t(work);
}

特点:

1.自动创建

2.由于栈的生命周期,函数结束就自动销毁

但是,如果在这个std::thread对象析构时,线程还在运行(joinable),程序必须直接终止(std::terminate)

其中,std::thread 对象(C++ 层面的“控制器”)

  • 它只是一个 C++ 对象
  • 用来:
    • 创建线程
    • 管理线程句柄
    • 调用 join() / detach()

而 操作系统线程(OS Thread)

  • 真正执行函数代码的东西
  • 由操作系统调度
  • 一旦创建,就独立于 C++ 对象存在

线程函数是由“操作系统线程”执行的
而不是由 std::thread 对象执行的


所有线程对象的生命周期必须覆盖线程执行期,如果做不到就要:

join()

detach()

否则 直接终止程序

1
t.join();

意思是:

“我等你跑完,然后我们一起安全退出”

  • 线程函数结束
  • OS 线程结束
  • std::thread 对象变为 non-joinable
  • 析构安全
1
t.detach();

意思是:

“我不管你了,你自生自灭”

  • OS 线程继续跑
  • std::thread 对象放弃控制权
  • 析构安全

但你必须保证线程访问的资源仍然活着

其中,joinable() 表示:
这个 std::thread 对象当前是否“仍然拥有一个尚未被回收的 OS 线程”。

如果返回 true,意味着:

  • 线程 还没被 join
  • 线程 还没被 detach
  • 或者 线程已经结束,但你还没回收它

堆(heap)

1
std::thread* t = new std::thread(work);

特点:

  • 手动管理
  • 生命周期不受作用域限制

但问题更大:

  • 忘记 delete → 内存泄漏
  • 异常中断 → delete 永远不会执行
  • 谁负责 join()?谁负责 delete逻辑混乱

所以在堆上最好使用智能指针自动管理。

std::unique_ptr<T> 有两个核心规则:

  1. 独占所有权
    • 同一时间只能有一个 owner
  2. 生命周期结束 → 自动释放资源

这一句:

1
auto t = std::make_unique<std::thread>(work);

等价写法是:

1
2
std::thread* raw = new std::thread(work);
std::unique_ptr<std::thread> t(raw);

也就是说:

  1. 在堆上 new 了一个 std::thread
  2. 线程立刻启动,开始执行 work
  3. unique_ptr 接管这个指针的“生杀大权”

启动线程:把一个“裸 this 指针”拷贝进新线程 auto t = std::make_unique\<std::thread>(&CameraProcessor::processingLoop, this); 这行代码会立刻启动一个新线程,在线程中执行 this->processingLoop()

线程只保存 this 的裸指针,不管理对象生命周期

如果对象先析构而线程还在跑,继续用 this → 未定义行为(可能直接崩)
// 最低安全写法:析构前一定要结束线程

1
2
3
4
~CameraProcessor() {
if (t && t->joinable())
t->join();
}