title: ctor initializer list with std::thread and this
body: <p>I have read some stuff about 'this' being unsafe in the initializer list of the constructor. I have a rather large app and I traced some undefined behavior to using std::thread with 'this' in the initializer list of a constructor. When I moved the std::thread construction out of the initializer list and into the constructor the app works without errors.</p>
  
  <p>I tried to reproduce the problem with an example but it runs perfectly.
  Can anybody explain why the combo of std::thread, 'this' and initializer list might give undefined behavior. I think it has to do with 'this' not being fully initialized when you call the std::thread constructor but that is just guessing.</p>
  
  <p>I would like to be able to reproduce the problem.
  Tried with g++4.9.2 and g++5.4 on ubuntu 16.04.
  I compiled with -g and -O0 to debug. Also tried with -O2 and -O3.</p>
  
  <pre><code>#include &lt;chrono&gt;
  #include &lt;condition_variable&gt;
  #include &lt;memory&gt;
  #include &lt;mutex&gt;
  #include &lt;thread&gt;
  
  //g++ -std=c++11 -g -O0 -pthread init_thread.cpp -o init_thread
  
  /* ------------------------------------------------------------------------- +
   |   TEMPLATE FUNCTIONS
   + ------------------------------------------------------------------------- */
  #if __cplusplus &lt; 201402L
  template&lt;typename T, typename... Args&gt;
  std::unique_ptr&lt;T&gt; make_unique(Args&amp;&amp;... args)
  {
    return std::unique_ptr&lt;T&gt;(new T(std::forward&lt;Args&gt;(args)...));
  }
  #endif
  
  
  /* ------------------------------------------------------------------------- +
   |   CLASSES
   + ------------------------------------------------------------------------- */
  class X
  {
  public:
      X() = delete;
  
      X(int x) : x_(x)
      {
          t_ = std::thread(&amp;X::foo, this);
          printf("Ctor X\n");
      }
  
      ~X()
      {
          {
              std::lock_guard&lt;std::mutex&gt; lck(mtxState_);
              state_ = State::terminated;
          }
          cv_.notify_one();
          if (t_.joinable())
          {
              t_.join();
          }
          printf("Dtor X\n");
      }
  
  private:
      enum class State
      {
          suspended,
          running,
          terminated
      };
  
      int x_;
      mutable std::mutex mtxState_;
      State state_ { State::running };
      mutable std::condition_variable cv_;
      std::thread t_;
  
      void foo()
      {
          while (state_ != State::terminated)
          {
              switch (state_)
              {
                  case State::suspended:
                      {
                          std::unique_lock&lt;std::mutex&gt; lck(mtxState_);
                          cv_.wait(lck, [this] { return state_ != State::suspended; });
                      }
                      break;
                  case State::running:
                      {
                          printf("do something X...\n");
                          std::this_thread::sleep_for(std::chrono::milliseconds(100));
                      }
                  default:
                      break;
              }
          }
      };
  };
  
  
  class I
  {
  public:
      I() = delete;
      I(int i) {};
  };
  
  
  class A : I
  {
  public:
      A() = delete;
  
      A(int a) : I(a), a_(a), x_obj_with_thread_(make_unique&lt;X&gt;(15)), t_(std::thread(&amp;A::foo, this))
      {
          printf("Ctor A\n");
      }
  
      ~A()
      {
          {
              std::lock_guard&lt;std::mutex&gt; lck(mtxState_);
              state_ = State::terminated;
          }
          cv_.notify_one();
          if (t_.joinable())
          {
              t_.join();
          }
          printf("Dtor A\n");
      }
  
  private:
      enum class State
      {
          suspended,
          terminated
      };
  
      int a_;
      mutable std::mutex mtxState_;
      State state_ { State::suspended };
      mutable std::condition_variable cv_;
      std::thread t_;
      std::unique_ptr&lt;X&gt; x_obj_with_thread_;
  
      void foo()
      {
          while (state_ != State::terminated)
          {
              switch (state_)
              {
                  case State::suspended:
                      {
                          std::unique_lock&lt;std::mutex&gt; lck(mtxState_);
                          cv_.wait(lck, [this] { return state_ != State::suspended; });
                      }
                      break;
                  default:
                      printf("do something A...\n");
                      break;
              }
          }
      };
  };
  
  class B : I
  {
  public:
  
      B() = delete;
  
      B(int b) : I(b), b_(b), x_obj_with_thread_(make_unique&lt;X&gt;(15))
      {
          t_ = std::thread(&amp;B::bar, this);
          printf("Ctor B\n");
      }
  
      ~B()
      {
          {
              std::lock_guard&lt;std::mutex&gt; lck(mtxState_);
              state_ = State::terminated;
          }
          cv_.notify_one();
          if (t_.joinable())
          {
              t_.join();
          }
          printf("Dtor B\n");
      }
  
  private:
      enum class State
      {
          suspended,
          terminated
      };
  
      int b_;
      mutable std::mutex mtxState_;
      State state_ { State::suspended };
      mutable std::condition_variable cv_;
      std::thread t_;
      std::unique_ptr&lt;X&gt; x_obj_with_thread_;
  
      void bar()
      {
          while (state_ != State::terminated)
          {
              switch (state_)
              {
                  case State::suspended:
                      {
                          std::unique_lock&lt;std::mutex&gt; lck(mtxState_);
                          cv_.wait(lck, [this] { return state_ != State::suspended; });
                      }
                      break;
                  default:
                      printf("do something B...\n");
                      break;
              }
          }
      };
  };
  
  
  void testA()
  {
      for (int i=0; i &lt; 100000; i++)
      {
          printf("A iteration %i\n", i);
          A a(15);
      }
  }
  
  void testB()
  {
      for (int i=0; i &lt; 100000; i++)
      {
          printf("B iteration %i\n", i);
          B b(15);
      }
  }
  
  int main() 
  {
      std::thread a(testA);
      std::thread b(testB);
      a.join();
      b.join();
      return 0;
  }
  </code></pre>