1

我做了一个简单的单例类。在运行测试时,我得到了一些奇怪的结果。

再次调用析构函数。

这是结果和我的代码。

结果:我希望析构函数被调用 4 次,因为我调用了GetInstance()4 次。但是Desctructor 被调用了5 次

Start Test
TestClass Constructor
   TestClass Destructor
   TestClass Destructor
   TestClass Destructor
   TestClass Destructor
   TestClass Destructor

单例.h

#ifndef SINGLETON_H_
#define SINGLETON_H_

#include "basictype.h"

namespace common {
namespace internal {

// Usage :
// MyClass mine = common::internal::Singleton<MyClass>::GetInstace();
// mine.foo();

// This Singleton class is maybe the best one avoiding memory allocation.
// See http://stackoverflow.com/questions/1008019/c-singleton-design-pattern/1008289#1008289
template <typename Type>
class Singleton {
 public:
  static Type& GetInstance() {
    static Type instance;
    return instance;
  }
 private:
  Singleton() {};

  DISALLOW_COPY_AND_ASSIGN(Singleton);
};

}  // namespace internal
}  // namespace common

#endif  // SINGLETON_H_

主程序

#include <iostream>
#include "singleton.h"

class TestClass {
 public:
  TestClass() {
    std::cout << "TestClass Constructor" << std::endl;
  }
  ~TestClass() {
    std::cout << "   TestClass Destructor" << std::endl;
  }
};

void runSingletonTest() {
  TestClass tc = common::internal::Singleton<TestClass>::GetInstance();
  TestClass tc2 = common::internal::Singleton<TestClass>::GetInstance();
  TestClass tc3 = common::internal::Singleton<TestClass>::GetInstance();
  TestClass tc4 = common::internal::Singleton<TestClass>::GetInstance();
}

int main(){
  std::cout << "Start Test" << std::endl;
  runSingletonTest();
  return 0;
}
4

5 回答 5

7

您的代码中实际上有 5 个实例TestClass

第一个是由

static Type instance;

使用默认构造函数。这会TestClass Constructor在您的输出中生成该行。

其他 4 个由

TestClass tc = common::internal::Singleton<TestClass>::GetInstance();
TestClass tc2 = common::internal::Singleton<TestClass>::GetInstance();
TestClass tc3 = common::internal::Singleton<TestClass>::GetInstance();
TestClass tc4 = common::internal::Singleton<TestClass>::GetInstance();

使用复制构造函数。复制构造函数由编译器生成,不输出任何内容(这就是为什么您TestClass Constructor在输出中只看到一个)。因此,有 5 个实例TestClass被销毁。

注意:您的Singleton班级并不是真正的单身人士。要正确遵循单例模式,您应该通过将(复制)构造函数和析构函数声明为来禁止复制和分配private

template <typename Type>
class Singleton {
public:
  static Type& GetInstance() {
    static Type instance;
    return instance;
  }
private:
  Singleton() {}
  ~Singleton() {}

  // Dont forget to declare these two. You want to make sure they
  // are unaccessable otherwise you may accidently get copies of
  // your singleton appearing.
  Singleton(const Singleton&);                // Don't Implement
  Singleton& operator=(const Singleton&);     // Don't implement
};

有一些关于C++ Singleton 设计模式的有用讨论。

如果 C++11 可用,最好使用

private:
  Singleton() = default;
  ~Singleton() = default;

  Singleton(const Singleton&) = delete;
  Singleton& operator=(const Singleton&) = delete;

这确保了没有人,甚至是类本身,都不能调用复制或复制分配函数。

于 2013-06-20T02:19:37.850 回答
1

所以拥有一个 Singleton 模板类是多余的,而且没有必要。单例是一种设计模式,而不是一种类型。

对于每个要制作单例的 T 类,只需:

  1. 添加instance静态函数
  2. 将 private 设为默认构造函数(并且仅在instance方法中调用它)
  3. 删除复制构造函数

这将防止创建多个类型 T 的实例。

尝试以下操作:

class TestClass {
public:

  // 1
  static TestClass& instance() { static TestClass x; return x; }

private:

  // 2
  TestClass() {
    std::cout << "TestClass Constructor" << std::endl;
  }

  // 3
  TestClass(const TestClass&) = delete;

  ~TestClass() {
    std::cout << "   TestClass Destructor" << std::endl;
  }
};

void runSingletonTest() {
  TestClass& tc = TestClass::instance();
  TestClass& tc2 = TestClass::instance();
  TestClass& tc3 = TestClass::instance();
  TestClass& tc4 = TestClass::instance();
}

现在您有 4 个对同一对象的引用,并且您不会意外创建第二个 TestClass。

于 2013-06-20T02:39:59.547 回答
0

模板中的“静态类型实例”正在创建另一个实例。

于 2013-06-20T02:21:58.350 回答
0

您错误地使用了 Meyer 的单例模式。

getInstance 应具有以下形式:

Singleton & GetInstance() {
   static Singleton instance;
   return instance;
}
于 2013-06-20T02:23:44.873 回答
0

要使其正常工作,您应该:

  1. MakeSingleton的构造函数、复制构造函数和赋值运算符受保护(非私有)。
  2. 从 Singleton 模板派生您的 TestClass。

    类TestClass:公共单例{...};

试着让我知道它是否适合你;)

于 2013-06-20T07:16:32.120 回答