std::thread::thread
来自 cppreference.cn
| thread() noexcept; |
(1) | (C++11 起) |
| thread( thread&& other ) noexcept; |
(2) | (C++11 起) |
| template< class F, class... Args > explicit thread( F&& f, Args&&... args ); |
(3) | (C++11 起) |
| thread( const thread& ) = delete; |
(4) | (C++11 起) |
构造一个新的 std::thread 对象。
1) 创建一个不表示任何线程的
std::thread 对象。2) 移动构造函数。构造
std::thread 对象以表示由 other 表示的执行线程。在此调用之后,other 不再表示任何执行线程。3) 创建一个新的
std::thread 对象并将其与一个执行线程关联。新的执行线程开始执行|
INVOKE(decay-copy(std::forward<F>(f)), |
(直至 C++23) |
|
std::invoke(auto(std::forward<F>(f)), |
(C++23 起) |
decay-copy 的调用在当前线程中求值,(C++23 前)由 auto 产生的值在当前线程中实体化,(C++23 起) 因此在参数求值和复制/移动过程中抛出的任何异常都在当前线程中抛出,而不会启动新线程。
只有当 std::decay<F>::type(C++20 前)std::remove_cvref_t<F>(C++20 起) 的类型与
std::thread 不同时,此重载才参与重载决议。|
如果满足以下任何条件,程序将不正确:
|
(C++20 前) |
|
如果以下任何一项为 false,则程序格式错误
|
(C++20 起) |
构造函数的调用完成 同步于 (synchronizes with) 新线程上 f 的副本的调用开始。
4) 复制构造函数被删除;线程不可复制。任何两个
std::thread 对象都不能表示相同的执行线程。目录 |
[编辑] 参数
| 其他 | - | 另一个线程对象,用于构造此线程对象 |
| f | - | 在新的线程中执行的 可调用 (Callable) 对象 |
| args | - | 传递给新函数的参数 |
[编辑] 后置条件
[编辑] 异常
3) 如果线程无法启动,则抛出 std::system_error。该异常可能表示错误条件
std::errc::resource_unavailable_try_again 或其他实现定义的错误条件。[编辑] 注意
线程函数的参数按值移动或复制。如果需要将引用参数传递给线程函数,则必须将其包装(例如,使用 std::ref 或 std::cref)。
函数的所有返回值都将被忽略。如果函数抛出异常,则调用 std::terminate。为了将返回值或异常传回调用线程,可以使用 std::promise 或 std::async。
[编辑] 示例
运行此代码
#include <chrono> #include <iostream> #include <thread> #include <utility> void f1(int n) { for (int i = 0; i < 5; ++i) { std::cout << "Thread 1 executing\n"; ++n; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } void f2(int& n) { for (int i = 0; i < 5; ++i) { std::cout << "Thread 2 executing\n"; ++n; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } class foo { public: void bar() { for (int i = 0; i < 5; ++i) { std::cout << "Thread 3 executing\n"; ++n; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } int n = 0; }; class baz { public: void operator()() { for (int i = 0; i < 5; ++i) { std::cout << "Thread 4 executing\n"; ++n; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } int n = 0; }; int main() { int n = 0; foo f; baz b; std::thread t1; // t1 is not a thread std::thread t2(f1, n + 1); // pass by value std::thread t3(f2, std::ref(n)); // pass by reference std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread std::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f std::thread t6(b); // t6 runs baz::operator() on a copy of object b t2.join(); t4.join(); t5.join(); t6.join(); std::cout << "Final value of n is " << n << '\n'; std::cout << "Final value of f.n (foo::n) is " << f.n << '\n'; std::cout << "Final value of b.n (baz::n) is " << b.n << '\n'; }
可能的输出
Thread 1 executing Thread 2 executing Thread 3 executing Thread 4 executing Thread 3 executing Thread 1 executing Thread 2 executing Thread 4 executing Thread 2 executing Thread 3 executing Thread 1 executing Thread 4 executing Thread 3 executing Thread 2 executing Thread 1 executing Thread 4 executing Thread 3 executing Thread 1 executing Thread 2 executing Thread 4 executing Final value of n is 5 Final value of f.n (foo::n) is 5 Final value of b.n (baz::n) is 0
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
|---|---|---|---|
| LWG 2097 | C++11 | 对于重载 (3),F 可以是 std::thread |
F 被限制 |
| LWG 3476 | C++20 | 重载 (3) 直接要求(衰变类型)F 和参数类型是可移动构造的 |
移除这些 要求[1] |
- ↑ 可移动构造性已经通过 std::is_constructible_v 间接要求。
[编辑] 参考资料
- C++23 标准 (ISO/IEC 14882:2024)
- 33.4.3.3 线程构造函数 [thread.thread.constr]
- C++20 标准 (ISO/IEC 14882:2020)
- 32.4.2.2 线程构造函数 [thread.thread.constr]
- C++17 标准 (ISO/IEC 14882:2017)
- 33.3.2.2 线程构造函数 [thread.thread.constr]
- C++14 标准 (ISO/IEC 14882:2014)
- 30.3.1.2 线程构造函数 [thread.thread.constr]
- C++11 标准 (ISO/IEC 14882:2011)
- 30.3.1.2 线程构造函数 [thread.thread.constr]
[编辑] 参阅
构造新的 jthread 对象( std::jthread 的公共成员函数) | |
| C 文档 为 thrd_create
| |