【问题标题】:Is managing resources in destructor for monostate classes/static members a bad idea in C++?在 C++ 中为单态类/静态成员管理析构函数中的资源是一个坏主意吗?
【发布时间】:2018-10-24 15:25:15
【问题描述】:

我正在尝试实现管理一些 std::thread 的单态类。线程一直在运行,直到标志变为等于 false。标志更改为 false 后 - 线程停止。但看起来我必须明确调用停止方法。在析构函数中调用它会给我带来运行时错误(在 GCC 4.8 for ARM、GCC 4.9 for 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 结合使用会产生相同的结果,但不会出错。线程一直在运行。

附言


将类设置为非单态可以解决运行时错误,但给我留下了这个问题。对于单态类/静态成员来说,管理资源是一种不好的做法吗?

【问题讨论】:

  • 如果你从不实例化一个类,它的析构函数永远不会被调用。
  • 您尝试的方法不起作用,您在问什么?
  • @NeilButterworth 它是单态的——它不需要自己实例化——所有成员都是静态的。并且 thouse 成员被实例化。请检查来源
  • @IGR94 如果它永远不会被实例化,则永远不会调用析构函数。
  • @juanchopanza 我在问为什么它实际上不起作用。尝试尽可能深入地挖掘

标签: c++ multithreading c++11 stdthread monostate


【解决方案1】:
 ~test();

应该在销毁任何“测试”对象之前调用。您不会在代码中创建“测试”对象,所以您是对的,

类的静态成员不与对象关联 类:它们是具有静态存储持续时间的独立对象或 在命名空间范围内定义的常规函数​​,在 程序。

【讨论】:

  • 但是当我执行test::go() 时,构造函数不是隐式调用的吗?
  • @IGR94 不,不是。
  • 好吧,我猜你的答案是第一位的,所以我接受它作为解决方案
【解决方案2】:

静态对象的构造函数调用之前main被执行,析构函数调用之后main完成(从atexit内部,通常)。

在析构函数中放一个断点,很容易看到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2014-07-13
    • 2018-03-17
    • 1970-01-01
    相关资源
    最近更新 更多