Вопросы о std :: thread class - PullRequest
       12

Вопросы о std :: thread class

0 голосов
/ 05 февраля 2019

Учитывая следующий заголовок класса:

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. Чтобы избежать непредвиденного поведения, необходимо ли перегрузить некоторые операторы класса?

1 Ответ

0 голосов
/ 05 февраля 2019

Вы вызываете неявные конструкторы, которые вы не определили (но были созданы для вас).Вы можете увидеть их в действии здесь:

#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

Уничтожение ...

Вы можете раскомментировать конструктор перемещения, если хотите также увидеть это в действии.

Чтобы прямо ответить на ваши вопросы:

Почему это происходит?С уважением, я ожидал только один экземпляр ThreadClass.

Это происходит потому, что вы передаете объект, поэтому дополнительные конструкторы, упомянутые в посте, вызываются несколько раз.

Чтобы избежать неожиданного поведения, необходимо ли перегрузить некоторые операторы класса?

Что вы подразумеваете под неожиданным поведением?Это выполняет именно так, как намерен C ++.Это хорошо определенное поведение для C ++.

...