简体   繁体   English

包含std :: threads的元素向量

[英]Vector of elements containing std::threads

I've got a class Tester containing an std:thread object, and an std::vector of Tester . 我有一个包含std:thread对象的类Tester和一个Testerstd::vector I understand that I can't copy threads, so the push_back is out of the question, but why emplace_back is not working? 我知道我无法复制线程,所以push_back是不可能的,但为什么emplace_back不起作用? Where is the copy in my code? 我的代码中的副本在哪里?

#include <iostream>
#include <thread>
#include <vector>
#include <functional>
#include <unistd.h>

class Tester
{
public:
    Tester(std::function<void(void)> func) : 
        th(func)
    {
    }

    ~Tester()
    {
        th.join()
    }

private:
    std::thread th;
};

std::vector<Tester> testers;

void InnerHelloWorld()
{
    std::cout << "Hello from the inner word!\n";
}

int main() {
    std::cout << "Hello World!\n";

    for(size_t i = 0 ; i < 4 ; i++)
    {
        testers.emplace_back(InnerHelloWorld);
    }

    sleep(1);

    return 0;
}

Theres a couple of minor issues in your code 您的代码中存在一些小问题

You missed the trailing semi-colon off of: 你错过了以下的尾随分号:

th.join()

But importantly, you need to give your class a move constructor - the default one is fine: 但重要的是,你需要给你的类一个移动构造函数 - 默认的是:

Tester(Tester&&) = default;

This is needed as when vectors resize themselves they need to move or copy their elements. 这是必需的,因为当向量调整大小时,他们需要移动或复制它们的元素。 A move constructor will generally be created for you but in your case having a custom destructor supresses it. 通常会为您创建移动构造函数,但在您的情况下,使用自定义析构函数会对其进行压缩。 See here . 看到这里

This will let your code compile, but then it'll throw an exception at runtime. 这将让你的代码编译,但它会在运行时抛出异常。 This is because you sometimes destruct from moved-from Testers which will call join on a moved from thread. 这是因为你有时会从被移动的Testers中移除,这将调用从线程移动的连接。 Fortunately this is an easy fix: 幸运的是,这是一个简单的修复:

~Tester()
 {
   if(th.joinable())
       th.join();
 }

Full working code: 完整的工作代码:

#include <iostream>
#include <thread>
#include <vector>
#include <functional>

#include <unistd.h>

class Tester
{
  public:
  Tester(std::function<void(void)> func) : 
    th(func)
  {
  }

  ~Tester()
  {
    if(th.joinable())
        th.join();
  }

  Tester(Tester&&) = default;

  private:
  std::thread th;
};

std::vector<Tester> testers;

void InnerHelloWorld()
{
  std::cout << "Hello from the inner word!\n";
}

int main() {
  std::cout << "Hello World!\n";

  for(size_t i = 0 ; i < 4 ; i++)
  {
    testers.emplace_back(InnerHelloWorld);
  }

  sleep(1);

  return 0;
}

You need to define move constructor for your class so it becomes MoveInsertable and will satisfy requirements of emplace method: 您需要定义移动构造函数的类,使其成为MoveInsertable和满足的要求emplace方法:

Tester(Tester && other) : 
    th(::std::move(other.th))
{
}

Another problem that will arise once you fix lack of move constructor is an attempt to join thread that is not nessesery joinable since actual thread could have been moved into another object. 修复缺少移动构造函数后出现的另一个问题是尝试连接不能连接的线程,因为实际的线程可能已被移动到另一个对象中。 So you need to add a corresponding check: 所以你需要添加一个相应的检查:

~Tester()
{
   if(th.joinable())
   {
       th.join();
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM