Является ли управление ресурсами в деструкторе классов-моностатов или статических членов плохой идеей в C++?
Я пытаюсь реализовать класс monostate, который управляет некоторым std::thread. Поток работает, пока флаг не станет равным false. После изменения флага на false - поток останавливается. Но похоже, что я должен вызывать метод остановки явно. Вызов его в деструкторе приносит мне ошибки времени выполнения (протестировано на GCC 4.8 для ARM, GCC 4.9 для x86_64 и MSVC 2017). Я прав, что такое поведение связано с
"Статические члены класса не связаны с объектами класса: они являются независимыми объектами со статической продолжительностью хранения или обычными функциями, определенными в области пространства имен, только один раз в программе".
так вызов деструктора опущен?
Пример кода:
#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
void runThread(const std::atomic<bool> &_isRunning) {
while (_isRunning) {
std::cout << "Me running.." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}
}
class test {
static std::thread thread;
static std::atomic<bool> isRunning;
public:
test();
~test();
static void go();
static void stop();
};
std::thread test::thread;
std::atomic<bool> test::isRunning{ false };
test::test() {}
void test::go() {
isRunning = true;
thread = std::thread(runThread, std::ref(isRunning));
}
void test::stop() {
isRunning = false;
if (thread.joinable()) {
thread.join();
}
}
test::~test() {
stop();
}
int main() {
test::go();
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Done here!!!!!!!!!!!!!!!!!";
// Will not crash anymore if uncomment
//test::stop();
return 0;
}
Использование std::async с std::feature дает тот же результат, но без ошибок. Нить просто продолжает работать.
PS
Создание класса non-monostate решает ошибки времени выполнения, но оставляет меня с этим вопросом. Является ли управление ресурсами плохой практикой для моностатических классов / статических членов?
2 ответа
~test();
должен быть вызван перед уничтожением любого "тестового" объекта. Вы не создаете "тестовые" объекты в своем коде, поэтому вы правы,
Статические члены класса не связаны с объектами класса: они являются независимыми объектами со статической продолжительностью хранения или обычными функциями, определенными в области пространства имен, только один раз в программе.
Конструктор статического объекта вызывается раньше main
выполняется, и деструктор вызывается после main
завершено (изнутри atexit
, как правило).
Поместите точку останова в деструктор, это легко увидеть.