Chuan Sun
Chuan Sun

Reputation: 77

Calling vector of threads from destructor

Why can't I call my vector of threads from the destructor? Is there some rule for using destructors?

void p ()
{
    std::cout << "thread running " << std::endl;
}

class VecThreads // Error: In instantiation of member function 'std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread> >::vector' requested here
{
public:
    std::vector<std::thread> threads;

    VecThreads() {
        threads.push_back(std::thread(p));
    }
    ~VecThreads()
    {
        threads[0].join();
    }
};

int main(int argc, const char * argv[]) {
    VecThreads h = VecThreads();
    //h.threads[0].join();  // delete deconstructor and use this works fine
  return 0;
}

The error I get:

Calling a private constructor of class 'std::__1::thread'

Upvotes: 3

Views: 355

Answers (1)

jfMR
jfMR

Reputation: 24788

The problem is in:

VecThreads h = VecThreads();

VecThreads has no move constructor, its generation is disabled (i.e., not declared) because it has a user-defined destructor. Therefore, the statement above calls VecThreads's copy constructor.

VecThreads contains a data member of type std::vector<std::thread> – which isn't copyable since an std::thread object is not copyable. Even though an std::vector<std::thread> is not copyable, it is movable, so a move constructor would, in principle, do the trick. You can explicitly enable the generation of the move constructor by adding the following inside VecThreads's definition:

VecThreads(VecThreads&&) = default;

Your original code does compile since C++17 without modification thanks to mandatory copy elision.

Upvotes: 3

Related Questions