C++中类的thread_local静态成员变量线程内初始化报错问题
类中thread_local静态成员变量的线程内初始化问题
问题代码
#include <cstdlib> #include <cstdio> #include <pthread.h> #include <atomic> #include <iostream> using namespace std; class A { public: thread_local static int i; }; typedef struct Args { A *a; int i; } Args; void* print(void* ptr) { Args *args = (Args*) ptr; thread_local int A::i = args->i; // args->a->i = args->i; cout << "(In thread) A.i = " << args->a->i << endl; return NULL; } int main() { pthread_t thread1, thread2; A *a = new A(); Args a1, a2; a1.a = a; a1.i = 10; pthread_create(&thread1, NULL, &print, &a1); a2.a = a; a2.i = 20; pthread_create(&thread2, NULL, &print, &a2); pthread_join(thread1, NULL); pthread_join(thread2, NULL); cout << "(In main) A.i = " << a->i << endl; return 0; }
编译错误
multithreaded_example.cpp: In function ‘void* print(void*)’: multithreaded_example.cpp:21:24: error: qualified-id in declaration before ‘=’ token thread_local int A::i = args->i; ^
错误原因
- 类静态成员定义位置违规:类内的
thread_local static int i;只是声明,必须在类外部完成定义,不能在函数内部重新声明并初始化。 - thread_local初始化方式错误:依赖线程参数的初始化不能用声明式赋值(这种初始化是在变量首次使用前自动完成的,无法获取线程传入的参数),只能在线程函数内直接对已定义的thread_local成员做赋值操作。
修正方案
步骤1:类外部定义thread_local静态成员
在类定义之后添加以下代码,完成静态成员的定义(C++标准强制要求类静态成员必须类外定义):
thread_local int A::i;
步骤2:修改线程函数的初始化逻辑
删除错误的thread_local int A::i = args->i;,直接改为赋值操作,每个线程会操作自己专属的A::i副本:
A::i = args->i;
修正后的完整代码
#include <cstdlib> #include <cstdio> #include <pthread.h> #include <atomic> #include <iostream> using namespace std; class A { public: thread_local static int i; }; // 类外部定义thread_local静态成员 thread_local int A::i; typedef struct Args { A *a; int i; } Args; void* print(void* ptr) { Args *args = (Args*) ptr; // 为当前线程的A::i副本赋值 A::i = args->i; cout << "(In thread) A.i = " << A::i << endl; return NULL; } int main() { pthread_t thread1, thread2; A *a = new A(); Args a1, a2; a1.a = a; a1.i = 10; pthread_create(&thread1, NULL, &print, &a1); a2.a = a; a2.i = 20; pthread_create(&thread2, NULL, &print, &a2); pthread_join(thread1, NULL); pthread_join(thread2, NULL); cout << "(In main) A.i = " << A::i << endl; return 0; }
运行结果
(In thread) A.i = 10 (In thread) A.i = 20 (In main) A.i = 0
每个线程拥有独立的A::i副本,main线程的副本未被赋值,因此显示默认初始化的0。
内容的提问来源于stack exchange,提问作者Aarati K
相关产品推荐
相关产品推荐

