C ++,再次调用单例类的析构函数

时间:2013-06-20 02:10:28

标签: c++ singleton

我做了一个简单的单身人士课程。 在运行测试时,我得到了一些结果。

再一次调用析构函数。

这是结果和我的代码。

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

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

singleton.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_

的main.c

#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;
}

5 个答案:

答案 0 :(得分:8)

您的代码中实际上有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 design pattern的一些有用的讨论。

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

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

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

这确保了任何人,甚至是类本身,都无法调用复制或复制赋值函数。

答案 1 :(得分:1)

因此拥有一个Singleton模板类是过度的,而不是必需的。 Singleton是一种设计模式,而不是一种类型。

对于您想要制作单身的每个T类,只需:

  1. 添加instance静态功能
  2. 将private设为默认构造函数(仅在instance方法中调用它)
  3. 删除复制构造函数
  4. 这将阻止创建多个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。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

你错误地使用了迈耶的单身人士模式。

getInstance应具有以下形式:

Singleton & GetInstance() {
   static Singleton instance;
   return instance;
}

答案 4 :(得分:0)

要使它正常工作,你应该:

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

    类TestClass:public Singleton {     ... };

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