代码之家  ›  专栏  ›  技术社区  ›  abc

为什么在传递给std::thread时会调用此构造函数3次?

  •  0
  • abc  · 技术社区  · 7 年前

    考虑以下代码片段:

    class Widget {
    public:
       Widget() { coutDefaultCtor();  }
       Widget(const Widget& w) { coutCopyCtor(); }
       Widget(Widget&& w) {  coutMoveCtor(); }
    
      ~Widget() = default; 
    
      void coutDefaultCtor() {
          std::cout << " called default Widget ctor " << std::endl;
      }
    
      void coutMoveCtor() {
          std::cout << " called move Widget ctor " << std::endl;
      }
    
      void coutCopyCtor() {
          std::cout << " called copy Widget ctor " << std::endl;
      }
    
      void doSomething() const { }
    };
    
    void takeWidget(const Widget& ref) {
      ref.doSomething();
    }
    
    int main() {
       Widget widget;
    
       std::thread t(takeWidget, widget);
       t.join();
       // expect 2 ctor calls
       // but calls 3
    }   
    

    据我所知, std::thread 将始终按值复制参数。 如果在某种情况下,入口点函数被定义为采用r值或常量l值引用(此处相同),则在内部将创建一个该类型的临时值,并将其作为r值传递。

    上述代码的输出打印, " called Widget ctor " 3次。 每个构造函数一个,默认、复制和移动。

    我只期待了两次,一次是为了 widget 正在调用默认构造函数 main() 以及由 标准::螺纹 这反过来又被移动了,为什么另一个看起来额外的建筑在这里发生?

    0 回复  |  直到 7 年前
        1
  •  1
  •   Hong Jiang    7 年前

    这是C++标准库的一个实现细节,在不同的实现中可能有所不同。还有更多的事情要做 std::thread t(takeWidget, widget) 而不仅仅是打电话 takeWidget(widget) . 例如,在GCC实现中 thread 构造函数调用 make_tuple() 这将根据参数的类型移动或复制参数。