【问题标题】:Thread calls destructor many times线程多次调用析构函数
【发布时间】:2014-08-22 21:05:36
【问题描述】:

我是 C++11 中 std::thread 的新手。我尝试将functor-object 传递给线程而不是lambda

然而,我得到的输出让我吃惊:析构函数似乎被调用了 6 次。

代码片段:

#include <iostream>
#include <thread>

struct A
{
  A()
  { 
    std::cout << "creating A" << std::endl; 
  }

  void operator()()
  {
    std::cout << "calling ()-operator" << std::endl;
  }

  ~A()
  { 
    std::cout << "destroying A" << std::endl;   
  }
};

int main()
{
  {
    std::thread t( (A()) );
    t.join();
  }
  std::cin.get();
}

我得到的输出 (msvc11) 是

creating A
calling ()-operator
destroying A
destroying A
destroying A
destroying A
destroying A
destroying A

非常感谢任何解释。!

【问题讨论】:

  • 我会添加一个复制构造函数来查看它被调用了多少次......
  • 您还可以将输出添加到复制和移动构造函数,以查看实现对对象的作用。但是,它是您特定标准库实现的实现细节。
  • 赞,复制构造函数被调用了 5 次,因此这 6 个 dtor 调用非常有意义。剩下的问题是:为什么有 5 个副本?
  • 您可能对此感兴趣。 stackoverflow.com/a/24191884/893693
  • @user3796535 移出的对象仍需要销毁。移动必须使源对象处于“未指定但有效”状态。 dtor 当然也会在此类对象上调用。

标签: c++ multithreading c++11 destructor


【解决方案1】:

您不会捕获可以创建对象的所有路径。给A添加一个拷贝构造函数:

A( A const &a )
{
    std::cout << "creating A (copy)" << std::endl;
}

【讨论】:

  • 感谢您的回答。正如我在上面的 cmets 中所说,我添加了复制和移动析构函数,并且该对象确实被复制/移动了。使用 std::ref 不会显示这种行为。但是,有什么解释为什么该对象会被复制这么多还是只是 msvc11 的实现?
  • @user3796535,它只是 msvc11 实现。据我所知,gcc 生成的程序只创建/销毁 A 对象两次。
猜你喜欢
  • 2012-07-12
  • 2018-12-04
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多