我刚刚开始用pthreads学习C++中的多线程。我正在使用以下代码:
struct ArgT{
int a;
int b;
ArgT(int a, int b)
: a(a), b(b)
{}
ArgT()
:a(0), b(0)
{}
};
void* worker(void* arg)
{
ArgT* myArg = (ArgT*) arg;
int* result = new int;
*result = myArg->a + myArg->b;
std::cout << "(void*)result: " << (void*) result << std::endl;
return (void*)result;
}
int main()
{
ArgT mainArg(2,3);
pthread_t p;
int* main_result;
pthread_create(&p, NULL, worker, (void*)&mainArg);
pthread_join(p, (void**)&main_result); //??
std::cout << "main_result: " << main_result << std::endl;
std::cout << "&main_result: "<< &main_result << std::endl;
printf("nResult = %dn", *main_result);
delete main_result;
return 0;
}
代码的输出如下
(void*)result: 0x7f07ac0008c0
main_result: 0x7f07ac0008c0
&main_result: 0x7fffb1aa0588
Result = 5
我的问题是pthread_join()
接受void**
作为第二个参数,它基本上是地址的地址。而我们在worker()
函数中返回类型为void*
的地址。这两种类型如何兼容?
pthread_join()
获取指针变量的地址。该变量将接收线程返回的指针值。它实际上也在做同样的事情:
void doIt(void (*f)(), void** ptr)
{
*ptr = f();
}
void* func()
{
return ...;
}
int main()
{
void *ptr;
doIt(func, &ptr);
// ptr holds whatever func() returns...
}
这两种类型如何兼容?
当void**
间接通过时,结果是类型为void*
的左值
您的程序有未定义的行为。这里有一个正确的方法:
void* void_main_result;
pthread_join(p, &void_main_result);
int* int_main_result = static_cast<int*>(void_main_result);
std::cout << "nResult = " << *int_main_result;
您可以通过在参数中分配结果来避免动态分配。这样就不需要返回值:
struct ArgRet {
ArgT args;
int ret;
} mainArg;
pthread_create(&p, NULL, worker, &mainArg);
std::cout << "nResult = " << mainArg.ret;
// in worker
ArgRet* myArg = static_cast<ArgRet*>(arg);
myArg->ret = myArg->args.a + myArg->args.b;
return arg; // or nullptr; doesn't really matter
使用std::thread而不是pthreads 的主要优势是什么
std::thread
适用于所有C++(11或更高版本(实现。pthreads只适用于POSIX系统。std::thread
的API也更容易使用,因为它是用C++而不是C编写的。
p.S.将指针转换为void*
是隐含的。我建议不要使用C样式强制转换。