【问题标题】:Can this be considered as a valid implementation of singleton class in C++?这可以被认为是 C++ 中单例类的有效实现吗?
【发布时间】:2021-07-25 11:10:56
【问题描述】:
#include <iostream>
using namespace std;

class Singleton {
public:
    int val;
    static int count;
    Singleton() {
        if (count == 1) throw 0;
        Singleton::count++;
        val = 100;
    }
};

int Singleton::count = 0;

int main () {
    try {
        Singleton a, b;
    } catch (...) {
        cout << "error\n";
    }
    return 0;
}

所以我们统计创建的对象个数,当count快要超过1时从构造函数中抛出。从构造函数中抛出会中止对象的创建吗?

【问题讨论】:

  • 我已经有 24 年没有接触过 C++ 了,但您肯定需要在 if (count == 1) throw 0;Singleton::count++; 周围进行一些同步吗?否则,线程 A 可以清除 if (count == 1),在它清除 Singleton::count++; 之前,线程 B 也可以清除 if (count == 1) - 你有两个实例(至少)。
  • 你对这门课有什么要求?
  • 把同步问题放在一边,你删除编译时机制以确保奇异性和正确的生命周期,并用运行时错误替换它们没有机制来解决生命周期问题......这个并不比流行的方法好。
  • 您是想找到一种在 C++ 中实现单例的正确方法,还是只是对这个特定(非常具体的)代码感到好奇?
  • @AlanBirtles 没有这样的要求,我只是对这种方法感到好奇。

标签: c++ oop design-patterns singleton


【解决方案1】:

C++11 及以上:

您将构造函数设为私有并在静态函数中定义一个静态实例。它同步构造,因此无论有多少线程尝试访问它,都会构造一次对象:

class Singleton {
private:
    Singleton() { /* ... */ }

public:
    static auto& instance() {
        static Singleton singleton;
        return singleton;
    }
};

C++11 之前的:

在 C++11(C++03、C++98)之前,没有同步对象构造的标准方法。您需要使用特定于操作系统的技巧才能使其正常工作。

如果您有一个单线程程序,因此不关心同步,您可以使用与上述相同的版本。

【讨论】:

  • 请注意,这仅适用于符合 C++11 及更高版本的编译器。在 C++11 之前,您必须使用同步。
  • @PaulMcKenzie 嗯,是的,但是 C++11 之前的标准不承认线程的存在。现在是 2021 年,也就是 C++11 标准化十年后。
  • 感谢您的回答。但是,我仍然不知道第二部分的答案,即从类构造函数中抛出异常是否会中止对象的创建?另外,我们如何验证对象是否被创建?
  • @VighneshNayak 是的,投掷会中止构建。并且在您第一次访问对象时,该对象已完成构建。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多