关于std::thread类的问题

Questions about std::thread class

本文关键字:问题 thread std 关于      更新时间:2023-10-16

考虑以下类标题:

class ThreadClass {
public:
ThreadClass();
~ThreadClass();
void operator()(int val);
void set(int val);
int get();
private:
int x;
};

以及以下实现:

ThreadClass::ThreadClass(): x(0) {
std::cout << "Constructing..." << std::endl;
}
ThreadClass::~ThreadClass() {
std::cout << "Destructing..." << std::endl;
}
void ThreadClass::operator()(int val) {
set(val);
std::cout << get() << std::endl;
set(val * 2);
std::cout << get() << std::endl;
}
void ThreadClass::set(int val) {
x = val;
}
int ThreadClass::get() {
return x;
}

启动以下main时,类析构函数会被调用多次而不是一次:

int main(int argc, char const *argv[]) {
std::thread x = std::thread(ThreadClass(), 10);
x.join();
return 0;
}
>>> Constructing...
>>> Destructing...
>>> Destructing...
>>> 10
>>> 20
>>> Destructing...

由于我对std::thread类的了解不太深入,我想问你:

  1. 为什么会发生这种情况?真诚地说,我期待的只是ThreadClass的一个实例
  2. 为了避免意外行为,是否有必要重载某些类运算符

您正在调用尚未定义(尚未为您创建)的隐式构造函数。你可以在这里看到他们的行动:

#include <thread>
#include <iostream>
class ThreadClass {
public:
ThreadClass() {
std::cout << "Constructing..." << std::endl;
}

ThreadClass(const ThreadClass& t) {
std::cout << "Copy constructing..." << std::endl;
this->x = t.x;
}

//   ThreadClass(ThreadClass&& t) {
//     std::cout << "Move constructing..." << std::endl;
//     this->x = t.x;
//   }

~ThreadClass() {
std::cout << "Destructing..." << std::endl;
}

void operator()(int val) {
set(val);
std::cout << get() << std::endl;
set(val * 2);
std::cout << get() << std::endl;
}
void set(int val) {
x = val;
}
int get() {
return x;
}
private:
int x;
};
int main(int argc, char const *argv[]) {
std::thread x = std::thread(ThreadClass(), 10);
x.join();
return 0;
}

输出:

正在构建。。。

复制正在构建。。。

复制正在构建。。。

正在破坏。。。

正在破坏。。。

10

20

正在破坏。。。

如果您想看到move构造函数也在运行,可以取消对其的注释。

直接回答您的问题:

为什么会发生这种情况?真诚地说,我期待的只是ThreadClass的一个实例。

之所以会发生这种情况,是因为您正在传递一个对象,所以文章中提到的其他构造函数会被多次调用。

为了避免意外行为,是否有必要重载某些类运算符?

您所说的意外行为是什么意思?这正是C++想要的。这是C++定义良好的行为。