在类的第一个/最后一个实例存在之前/之后调用一对函数.有没有更好的方法?

Call a pair of functions before/after the first/last instance of a class exists. Is there a better way?

本文关键字:函数 有没有 更好 方法 调用 最后一个 第一个 实例 存在 之后      更新时间:2023-10-16

我有一对函数initshutdown以及一些类RefTest

我需要在首次实例化RefTest时调用init,并在销毁RefTest的最后一个实例时调用shutdown。这也可能在一个程序中多次发生。

我想出的一个实现如下所示。但这对我来说似乎并不理想(例如,它不是线程安全的(。 我想过使用std::shared_ptr并将这些功能放在类 ctor/dtor 中,但我似乎无法让它工作。

有没有更好的方法可以做到这一点?

测试实现:

#include <iostream>
void init() { std::cout << "init() called" << std::endl; }
void shutdown() { std::cout << "shutdown() called" << std::endl; }
static size_t s_refCount = 0;
class RefTest
{
public:
explicit RefTest()
{
if(s_refCount++ == 0) init();
std::cout << "ctor()" << std::endl;
}
~RefTest()
{
std::cout << "dtor()" << std::endl;
if(--s_refCount == 0) shutdown();
}
};
int main(int argc, char *argv[])
{
{
RefTest t1;
RefTest t2;
RefTest t3;
}
RefTest t4;
return 0;
}

输出:

init() called
ctor()
ctor()
ctor()
dtor()
dtor()
dtor()
shutdown() called
init() called
ctor()
dtor()
shutdown() called
但这

对我来说似乎并不理想(例如,它不是线程安全的(。

std::atomic<int>帮助解决这个问题 - 但只是问题的一部分。它可以使计数器线程安全,这样您就不会尝试调用init/shutdown太多次。

它不会解决在第一次调用仍在执行时第二次调用构造函数的问题。(然后使用部分构造的对象(

有没有更好的方法可以做到这一点?

普遍接受的最佳做法是为每个类分配一个作业。

例:

#include <iostream>
#include <atomic>

// one class, one job
struct initialiser
{
initialiser()
{
if (0 == s_refCount++) init();
}
initialiser(initialiser const&)
{
++s_refCount;
}
initialiser& operator=(initialiser const&)
{
++s_refCount;
return *this;
}
~initialiser()
{
if(--s_refCount == 0) shutdown();
}
private:
void init() { std::cout << "init() called" << std::endl; }
void shutdown() { std::cout << "shutdown() called" << std::endl; }
static std::atomic<size_t> s_refCount;
};
std::atomic<size_t> initialiser::s_refCount { 0 };

// one class, one job. Allow encapsulation to do the reference counting
class RefTest
{
public:
explicit RefTest()
{
std::cout << "ctor()" << std::endl;
}
// rule of 5
RefTest(RefTest const &) = default;
RefTest(RefTest &&) = default;
RefTest& operator=(RefTest const &) = default;
RefTest& operator=(RefTest &&) = default;
~RefTest()
{
std::cout << "dtor()" << std::endl;
}
private:
initialiser init_;
};
int main(int argc, char *argv[])
{
{
RefTest t1;
RefTest t2;
RefTest t3;
}
RefTest t4;
return 0;
}

预期产出:

init() called
ctor()
ctor()
ctor()
dtor()
dtor()
dtor()
shutdown() called
init() called
ctor()
dtor()
shutdown() called

另请注意不违反 3/5 规则

相关文章: