How to create a vector of a specific class in c++ that includes thread objects in it?

89 views Asked by At

I have created a class named AnalyzerCore in c++ like below:

AnalyzerCore.h

class AnalyzerCore
{
private:
    thread AnalyzerThread;
    void AnalyzerFunc();
    bool isRunning;
    int id;

public:
    AnalyzerCore(int id_in);
    ~AnalyzerCore();
};

AnalyzerCore.cpp

void AnalyzerCore::AnalyzerFunc()
{
    while (isRunning) {
        cout << "Analyzer "<< id << " is active!\n";
        this_thread::sleep_for(chrono::seconds(1));
    }
}

AnalyzerCore::AnalyzerCore(int id_in)
{
    id = id_in;
    isRunning = true;
    AnalyzerThread = thread(&AnalyzerCore::AnalyzerFunc, this);
}

AnalyzerCore::~AnalyzerCore()
{
    isRunning = false;
    if (AnalyzerThread.joinable()) AnalyzerThread.join();
}

and in the main.cpp, I have maked a vector of AnalyzerCore and push_back 2 instance of the calss

int main()
{
    vector<AnalyzerCore> a;
    a.push_back(AnalyzerCore(0));
    a.push_back(AnalyzerCore(1));
    this_thread::sleep_for(chrono::seconds(10));
    std::cout << "Hello World!\n";
}

But when I have built above, I have faced following error:

'AnalyzerCore::AnalyzerCore(const AnalyzerCore &)': attempting to reference a deleted function

What's wrong with my code and what do you suggest to fix it? thank you!

2

There are 2 answers

9
463035818_is_not_an_ai On

You cannot copy a std::thread (what would that mean?), hence you cannot copy a AnalyzerCore.

You can use std::vector::emplace_back() to construct the AnalyzerCore objects directly in the vector, rather than constructing a temporary and then copying or moving it into the vector.

Moreover, when the vector grows, it has to reallocate and move or copy elements. As you cannot copy, you need to add a move constructor (when the compiler does not generate it):

#include <thread>
#include <vector>

struct foo {
    std::thread t;
    int value;
    foo(int value) : value(value) {}
    foo(foo&&) = default;
    ~foo(){}
};

int main() {
    std::vector<foo> ts;
    ts.emplace_back(42);
    ts.emplace_back(42);
    ts.emplace_back(42);
}

Live Demo

4
Jack Morozov On

First off, switch all the push_back(AnalyzerCore(x)) calls to emplace_back(x). This will force the std::vector to call the AnalyzerCore(AnalyzerCore&&) constructor rather than the AnalyzerCore(const AnalyzerCore&) constructor. (The former takes an xvalue, and the latter takes a lvalue - see What are rvalues, lvalues, xvalues, glvalues, and prvalues?)

std::vector requires this to be explicitly defined for it to accept your class.

#include <thread>
#include <iostream>

class AnalyzerCore
{
private:
    std::thread AnalyzerThread;
    void AnalyzerFunc();
    bool isRunning;
    int id;

public:
    AnalyzerCore(int id_in);

    AnalyzerCore(const AnalyzerCore&) = delete;
    AnalyzerCore(AnalyzerCore&&) = default;

    ~AnalyzerCore();
};

As soon as you define any constructor, all other default constructors that would have made your class valid for std::vector's type traits are removed.

To remove support for copying, add the = delete; constructor.

To add support for xvalue copying, add the &&) = default; for the default xvalue constructor.