c++ - 具有原子成员的单例类的实现
问题描述
我正在尝试实现一个类来跟踪多线程代码的性能,并且遇到了以下问题。
跟踪器应该有一个实例,因此是单例模式。为了计算所有线程中的对象创建和函数执行,我认为使用原子成员是个好主意。但我似乎无法找出正确的实现。
这是我想做的最小代码:
#include <atomic>
#include <iostream>
class Counter
{
public:
static Counter& instance()
{
return instance_;
};
void increment()
{
counter_++;
};
private:
Counter ()
{
std::cout << "ctor counter" << std::endl;
};
~Counter ()
{
std::cout << "counter_: " << counter_ << std::endl;
std::cout << "dtor counter" << std::endl;
}
static Counter instance_;
std::atomic<int> counter_{0};
//int counter_ = 0;
};
Counter Counter::instance_ = Counter();
int main(void)
{
Counter::instance().increment();
Counter::instance().increment();
Counter::instance().increment();
return 0;
}
如果counter_
变量是int
,它可以正常工作,但不是线程安全的。如果是atomic<int>
,那么编译器会告诉我:
g++ foo.cc
foo.cc:34:38: error: use of deleted function 'Counter::Counter(const Counter&)'
Counter Counter::instance_ = Counter();
^
foo.cc:4:7: note: 'Counter::Counter(const Counter&)' is implicitly deleted because the default definition would be ill-formed:
class Counter
^~~~~~~
foo.cc:4:7: error: use of deleted function 'std::atomic<int>::atomic(const std::atomic<int>&)'
In file included from foo.cc:1:0:
/usr/include/c++/7/atomic:668:7: note: declared here
atomic(const atomic&) = delete;
^~~~~~
我不确定我是否完全理解这个问题。任何解释/解决方案将不胜感激。
干杯
解决方案
您可以通过std::atomic<int> counter_{0};
简单地成为static
类成员而不是每个实例的一部分来简化。(因为您要确保该类只有一个实例。)
或者,如果您只是以这种方式使用“单例”返回对静态对象的引用,只需创建其所有成员static
,这样您就不需要首先获取指向它的单个实例的指针。然后它可以被namespace{}
公有和私有静态成员函数美化。我认为“单例”的唯一要点是通过使用带有非常量初始化程序的函数范围静态变量来延迟初始化它直到静态初始化之后,但你没有这样做。
实际问题出在类的复制构造函数中,您的静态初始化程序使用您编写它的方式。 它构造一个临时变量Counter();
,然后将其复制到静态instance_
变量。
您可以编译为 C++17,保证删除该副本(在 Godbolt 上使用 g++-std=gnu++17
且源代码不变),或者您可以重写初始化程序
Counter Counter::instance_; // default construct
Counter Counter::instance_{}; // explicitly default construct
两者都适用于g++-std=gnu++11
推荐阅读
- swift - 为什么我的动画只能在预览中使用?
- python - 尽管确认了 dtype=ndarray,但我无法从 scipy 写入 WAV 文件?
- electron - 无法在 Sentry 上获得可读的电子崩溃报告
- python - 字符串变量未在 Python 中的 SQL 的 SELECT WHERE 查询中传递
- microsoft-graph-api - Microsoft one note graph api 不会在部分中加载页面
- python - Matplotlib 创建平滑图
- python - Django Visual Studio 环境“....”不可用
- google-cloud-platform - 计算引擎备份
- php - MYSQL如何比较两个表的价格并显示所有结果
- python-3.x - python - 如何通过从list1中获取1个元素和从list2中获取其余元素等从2个列表中获取组合