Passing anonymous object to thread does not return

I'm passing two separate anonymous class objects to two different threads. It's not clear why the first object does not return. I should get:

1
2
C1
C2


If I change the C objects to non-anonymous objects then both C1 and C2 return. Anyone have an explanation?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <thread>
#include <memory>
#include <iostream>

class R
{
  std::unique_ptr<std::thread> th;
  public:
  R(void) { };
  ~R(void) { };
  virtual void poll(void) = 0;
  void init_th(void) { th = std::make_unique<std::thread>(&R::poll, this); };
  void deinit_th(void) { th->join(); };
};

class C : public R
{
  int n;
  public:
  C(int n) { this->n = n; init_th(); };
  ~C(void) { deinit_th(); };
  void poll(void) { std::cout << "C" << n << std::endl; while (1); };
};

int main()
{
  C(1);                                                                                                                                                                                      
  C(2);
  //C c1(1);                                                                                                                                                                                      
  //C c2(2);
  while (1);
  return 0;
}
Last edited on
I know, seems the destructor of C is being called rightaway within the scope of the line instead of the scope of main. As a result the program is immediately waiting to join C1.
seems the destructor of C is being called rightaway within the scope of the line

Yes. Temporary objects are destroyed at the end of the full-expression that creates them. The "end of the full expression" is intuitively the semicolon at the end of the line.

Classes with virtual functions should almost always have a virtual destructor.

Prefer member initializer lists over assignment in constructors.
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-initialize

A special member with empty braces is considered to be user-provided and therefore nontrivial. Trivial special members allow more opportunity for optimizations. As such, if you do specify special members, avoid empty braces. Instead, explicitly default them or allow them to be implicitly generated.
virtual ~R() = default;
Not all defaulted special members are trivial. This one is not, but it's a good habit regardless.

Make single-argument constructors explicit by default.
explicit C(int m): n{m} { init_th(); }
A non-explicit constructor with one parameter is called a converting constructor. Only converting constructors are usable in implicit conversions. Mostly, such conversions are undesirable. In this case, for example, it makes no sense for int to be acceptable where C is expected, so this constructor should be explicit.

Don't specify parameters of type void. It has no purpose and is therefore a waste of time.
Thank you
Topic archived. No new replies allowed.