首页 > 其他分享 >单例以及模板类的静态成员变量的生命周期

单例以及模板类的静态成员变量的生命周期

时间:2022-09-07 23:00:26浏览次数:82  
标签:生命周期 CGFunctionClass nullptr ptr flag static 单例 OnceSingle 模板

我们有如下的单例设计模式的实现:

template <typename T>
class OnceSingle {
public:
    OnceSingle() = delete;
    OnceSingle& operator=(const OnceSingle<T>& m) = delete;
    ~OnceSingle() = default;

    class CGFunctionClass {
        public:
            ~CGFunctionClass() {
                if (m_ptr != nullptr) {
                    delete m_ptr;
                    m_ptr = nullptr;
                }
            }
    };

    static T* getInstance() {
        std::call_once(s_flag, InitPtr);
        return m_ptr;
    }

private:
    static void InitPtr() {
        m_ptr = new T();
        static CGFunctionClass cg;
    }

private:
    static T* m_ptr;
    static std::once_flag s_flag;
};

template<typename T>
T* OnceSingle<T>::m_ptr = nullptr;

template<typename T>
std::once_flag OnceSingle<T>::s_flag;

有如下的单元测试函数:

TEST(MyUtil, test_singleton) {
    int *raw_ptr = OnceSingle<int>::getInstance();
    int *same_raw_ptr = OnceSingle<int>::getInstance();
    EXPECT_EQ(raw_ptr, same_raw_ptr);
    raw_ptr = nullptr;
    same_raw_ptr = nullptr;
}

在这个模板单例类中,存在一个裸指针 m_ptr,当我们的单元测试结束的时候,静态对象 static CGFunctionClass cg会进行析构,从而保证了这个裸指针所指向的对象也能够得到析构,从而避免了内存泄漏。

注意到这个静态CGFunctionClass的对象cg,是与 new T 同时出现的。

那么我们能不能将这个cg对象定义为这个类的静态成员变量呢?这样能够让代码的结构更加清晰。同时也让这个静态变量在析构的时候能够析构这个裸指针。

答案是否定的!

现在我们进行分析,我们有如下代码


template <typename T>
class OnceSingle {
public:
    OnceSingle() = delete;
    OnceSingle& operator=(const OnceSingle<T>& m) = delete;

    ~OnceSingle() = default;
    class CGFunctionClass {
        public:
            ~CGFunctionClass() {
                if (m_ptr != nullptr) {
                    delete m_ptr;
                    m_ptr = nullptr;
                }
            }
    };

    static T* getInstance() {
        std::call_once(s_flag, InitPtr);
        return m_ptr;
    }
private:
    static void InitPtr() {
        // s;
        // cg;
        m_ptr = new T();
    }

private:
    static T* m_ptr;
    static std::once_flag s_flag;
    static CGFunctionClass cg;
    static MyString s;
};

template<typename T>
T* OnceSingle<T>::m_ptr = nullptr;

template<typename T>
std::once_flag OnceSingle<T>::s_flag;

template<typename T>
typename OnceSingle<T>::CGFunctionClass OnceSingle<T>::cg;

template<typename T>
MyString OnceSingle<T>::s("Class Static Variable");

我们对 MyString 这个类型的构造函数和析构函数增加了字符串输出函数,使其在构造和析构的时候能够打印出信息。我们继续运行之前的单元测试,发现这个 s 对象的并没有被构造,更不用说析构了,由此可知 cg 这个变量同时也没有构造和析构,因此上述代码的执行会造成内存泄漏的问题。
我们把 InitPtr 函数中注释掉的两行取消注释,发现 s 对象成功构造了。
查阅《C++ Primer》 p588 有相关描述
image

C++中模板类的静态成员变量,只有在其使用时,才会进行构造
我们把上述代码中 InitPtr 的两行取消注释, 我们发现, 在程序的一开始就会输出 "Class Static Variable", 说明这个静态变量构造成功了。

如此一来,还是要在 InitPtr 函数中增加与单例对象无关的代码,为了避免发生内存泄漏,仍采用第一种写法。

标签:生命周期,CGFunctionClass,nullptr,ptr,flag,static,单例,OnceSingle,模板
From: https://www.cnblogs.com/qwerty-ll/p/16667449.html

相关文章

  • 【django学习-11】模板3:自定义标签与过滤器
    前言:Django虽然内置了二十多种标签和六十多种过滤器,但是为了给Web开发者提供更好使用体验,Django也提供了自定义标签与过滤器的功能。当内置标签与过滤器满足不了实际......
  • zabbix用户,角色,权限,模板管理
    zabbix用户,角色,权限,模板管理用户组用户角色用户使用刚才创建的用户登录模板组模板模板的监控项可以自己创建也可以从其他模板复制......
  • 单例模式
    单例就是只有一个实例对象,即在整个程序中,同一个类始终只有一个对象进行操作。这样可以极大的减少内存开支和系统的性能开销。这种模式提供了一种创建对象的最佳方式,让类负......
  • 【django学习-09】模板1:万能的句点号
    前言:Django作为web框架,需要一种很便捷的方法动态的生成HTML网页,因此有了模板这个概念;Django内置的模板引擎包含模板上下文、标签和过滤器,各功能说明如下:模板上下文,以变......
  • django中的模板层简介
    1.什么是模板层模板层可以根据视图中传递的字典数据动态生产相应的HTML页面2.模板层的配置1.在项目下创建一个与同名文件夹平行的templates文件夹2.在settings.py中的T......
  • 通过预绑定方法模式实现单例模式
    什么是预绑定方法模式预绑定方法模式是一种将对象方法绑定为函数的模式。要实现该模式,只需要一个单例对象----模块(module)当你在python中执行import语句导入模块时,无论i......
  • 简单定义一个生命周期
    简单定义一个拥有create,willStateUpdate和shouldStateUpdate三个类似生命周期的类,名字随意,不要介意classState{constructor(){this.state={hehe:"9"};......
  • 浅析UE4 Actor&Actor生命周期
    首先说明一下关于UE4中一些对象的名字前缀吧,虽然这个不是这一关于Actor的内容,但是后续都要用到,所以就先说明白。关于Class类前缀:派生自 Actor 的类前缀为A,比如ACont......
  • 大厂HR强烈推荐的简历模板
     简历,是求职生涯中厚积薄发的成果,是展示自身价值的产品说明书。一份合格甚至优秀简历,是你的名片,用简练的语言,用直观的数字,将你自身的社会价值清晰体现出来,帮助你......
  • 模板语法之继承
    什么是模板继承模板继承就是指可以使父模板的内容重用,子模板直接继承父模板的全部内容,并可以覆盖父模板中相应的块继承的语法父模板中:1.用block标签标识中哪些在子模板......